adds tests to SrpSetPassword(), SrpSetVerifier(), SrpGetVerifier();

adds SrpGenPublic() and SrpSetPrivate() with unit tests;
fixes k with left pad at g;
adds new error SRP_CALL_ORDER_E to force the functions to be called in the right order.
This commit is contained in:
Moisés Guimarães
2015-07-25 21:03:36 -03:00
parent 6d5efccc55
commit 6ee788277f
5 changed files with 318 additions and 41 deletions

View File

@ -30,20 +30,19 @@
#ifdef WOLFCRYPT_HAVE_SRP
static char user[] = "user";
static byte username[] = "user";
static word32 usernameSz = 4;
static byte password[] = "password";
static word32 passwordSz = 8;
static byte N[] = {
0x00, 0xc0, 0x37, 0xc3, 0x75, 0x88, 0xb4, 0x32, 0x98, 0x87, 0xe6, 0x1c,
0x2d, 0xa3, 0x32, 0x4b, 0x1b, 0xa4, 0xb8, 0x1a, 0x63, 0xf9, 0x74, 0x8f,
0xed, 0x2d, 0x8a, 0x41, 0x0c, 0x2f, 0xc2, 0x1b, 0x12, 0x32, 0xf0, 0xd3,
0xbf, 0xa0, 0x24, 0x27, 0x6c, 0xfd, 0x88, 0x44, 0x81, 0x97, 0xaa, 0xe4,
0x86, 0xa6, 0x3b, 0xfc, 0xa7, 0xb8, 0xbf, 0x77, 0x54, 0xdf, 0xb3, 0x27,
0xc7, 0x20, 0x1f, 0x6f, 0xd1, 0x7f, 0xd7, 0xfd, 0x74, 0x15, 0x8b, 0xd3,
0x1c, 0xe7, 0x72, 0xc9, 0xf5, 0xf8, 0xab, 0x58, 0x45, 0x48, 0xa9, 0x9a,
0x75, 0x9b, 0x5a, 0x2c, 0x05, 0x32, 0x16, 0x2b, 0x7b, 0x62, 0x18, 0xe8,
0xf1, 0x42, 0xbc, 0xe2, 0xc3, 0x0d, 0x77, 0x84, 0x68, 0x9a, 0x48, 0x3e,
0x09, 0x5e, 0x70, 0x16, 0x18, 0x43, 0x79, 0x13, 0xa8, 0xc3, 0x9c, 0x3d,
0xd0, 0xd4, 0xca, 0x3c, 0x50, 0x0b, 0x88, 0x5f, 0xe3
0xD4, 0xC7, 0xF8, 0xA2, 0xB3, 0x2C, 0x11, 0xB8, 0xFB, 0xA9, 0x58, 0x1E,
0xC4, 0xBA, 0x4F, 0x1B, 0x04, 0x21, 0x56, 0x42, 0xEF, 0x73, 0x55, 0xE3,
0x7C, 0x0F, 0xC0, 0x44, 0x3E, 0xF7, 0x56, 0xEA, 0x2C, 0x6B, 0x8E, 0xEB,
0x75, 0x5A, 0x1C, 0x72, 0x30, 0x27, 0x66, 0x3C, 0xAA, 0x26, 0x5E, 0xF7,
0x85, 0xB8, 0xFF, 0x6A, 0x9B, 0x35, 0x22, 0x7A, 0x52, 0xD8, 0x66, 0x33,
0xDB, 0xDF, 0xCA, 0x43
};
static byte g[] = {
@ -51,7 +50,46 @@ static byte g[] = {
};
static byte salt[] = {
'r', 'a', 'n', 'd', 'o', 'm'
0x80, 0x66, 0x61, 0x5B, 0x7D, 0x33, 0xA2, 0x2E, 0x79, 0x18
};
static byte verifier[] = {
0x24, 0x5F, 0xA5, 0x1B, 0x2A, 0x28, 0xF8, 0xFF, 0xE2, 0xA0, 0xF8, 0x61,
0x7B, 0x0F, 0x3C, 0x05, 0xD6, 0x4A, 0x55, 0xDF, 0x74, 0x31, 0x54, 0x47,
0xA1, 0xFA, 0x9D, 0x25, 0x7B, 0x02, 0x88, 0x0A, 0xE8, 0x5A, 0xBA, 0x8B,
0xA2, 0xD3, 0x8A, 0x62, 0x46, 0x8C, 0xEC, 0x52, 0xBE, 0xDE, 0xFC, 0x75,
0xF5, 0xDB, 0x9C, 0x8C, 0x9B, 0x34, 0x7A, 0xE7, 0x4A, 0x5F, 0xBB, 0x96,
0x38, 0x19, 0xAB, 0x24
};
static byte a[] = {
0x37, 0x95, 0xF2, 0xA6, 0xF1, 0x6F, 0x0D, 0x58, 0xBF, 0xED, 0x44, 0x87,
0xE0, 0xB6, 0xCC, 0x1C, 0xA0, 0x50, 0xC6, 0x61, 0xBB, 0x36, 0xE0, 0x9A,
0xF3, 0xF7, 0x1E, 0x7A, 0x61, 0x86, 0x5A, 0xF5
};
static byte A[] = {
0x8D, 0x28, 0xC5, 0x6A, 0x46, 0x5C, 0x82, 0xDB, 0xC7, 0xF6, 0x8B, 0x62,
0x1A, 0xAD, 0xA1, 0x76, 0x1B, 0x55, 0xFF, 0xAB, 0x10, 0x2F, 0xFF, 0x4A,
0xAA, 0x46, 0xAD, 0x33, 0x64, 0xDE, 0x28, 0x2E, 0x82, 0x7A, 0xBE, 0xEA,
0x32, 0xFC, 0xD6, 0x14, 0x01, 0x71, 0xE6, 0xC8, 0xC9, 0x53, 0x69, 0x55,
0xE1, 0xF8, 0x3D, 0xDD, 0xC7, 0xD5, 0x21, 0xCE, 0xFF, 0x17, 0xFC, 0x23,
0xBF, 0xCF, 0x2D, 0xB0
};
static byte b[] = {
0x2B, 0xDD, 0x30, 0x30, 0x53, 0xAF, 0xD8, 0x3A, 0xE7, 0xE0, 0x17, 0x82,
0x39, 0x44, 0x2C, 0xDB, 0x30, 0x88, 0x0F, 0xC8, 0x88, 0xC2, 0xB2, 0xC1,
0x78, 0x43, 0x2F, 0xD5, 0x60, 0xD4, 0xDA, 0x43
};
static byte B[] = {
0xB5, 0x80, 0x36, 0x7F, 0x50, 0x89, 0xC1, 0x04, 0x42, 0x98, 0xD7, 0x6A,
0x37, 0x8E, 0xF1, 0x81, 0x52, 0xC5, 0x7A, 0xA1, 0xD5, 0xB7, 0x66, 0x84,
0xA1, 0x3E, 0x32, 0x82, 0x2B, 0x3A, 0xB5, 0xD7, 0x3D, 0x50, 0xF1, 0x58,
0xBD, 0x89, 0x75, 0xC7, 0x51, 0xCF, 0x6C, 0x03, 0xD4, 0xCA, 0xD5, 0x6E,
0x97, 0x4D, 0xA3, 0x1E, 0x19, 0x0B, 0xF0, 0xAA, 0x7D, 0x14, 0x90, 0x80,
0x0E, 0xC7, 0x92, 0xAD
};
static void test_SrpInit(void)
@ -76,13 +114,13 @@ static void test_SrpSetUsername(void)
AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE));
/* invalid params */
AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetUsername(NULL, user));
AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetUsername(&srp, NULL));
AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetUsername(NULL, username, usernameSz));
AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetUsername(&srp, NULL, usernameSz));
/* success */
AssertIntEQ(0, wc_SrpSetUsername(&srp, user));
AssertIntEQ((int) XSTRLEN(user), srp.userSz);
AssertIntEQ(0, XMEMCMP(srp.user, user, srp.userSz));
AssertIntEQ(0, wc_SrpSetUsername(&srp, username, usernameSz));
AssertIntEQ((int) usernameSz, srp.userSz);
AssertIntEQ(0, XMEMCMP(srp.user, username, usernameSz));
wc_SrpTerm(&srp);
}
@ -92,7 +130,14 @@ static void test_SrpSetParams(void)
Srp srp;
AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE));
AssertIntEQ(0, wc_SrpSetUsername(&srp, user));
/* invalid call order */
AssertIntEQ(SRP_CALL_ORDER_E, wc_SrpSetParams(&srp, N, sizeof(N),
g, sizeof(g),
salt, sizeof(salt)));
/* fix call order */
AssertIntEQ(0, wc_SrpSetUsername(&srp, username, usernameSz));
/* invalid params */
AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetParams(NULL, N, sizeof(N),
@ -119,6 +164,117 @@ static void test_SrpSetParams(void)
wc_SrpTerm(&srp);
}
static void test_SrpSetPassword(void)
{
Srp srp;
byte v[64];
word32 vSz = 0;
AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE));
AssertIntEQ(0, wc_SrpSetUsername(&srp, username, usernameSz));
/* invalid call order */
AssertIntEQ(SRP_CALL_ORDER_E,
wc_SrpSetPassword(&srp, password, passwordSz));
AssertIntEQ(SRP_CALL_ORDER_E,
wc_SrpGetVerifier(&srp, v, &vSz));
/* fix call order */
AssertIntEQ(0, wc_SrpSetParams(&srp, N, sizeof(N),
g, sizeof(g),
salt, sizeof(salt)));
/* invalid params */
AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetPassword(NULL, password, passwordSz));
AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetPassword(&srp, NULL, passwordSz));
/* success */
AssertIntEQ(0, wc_SrpSetPassword(&srp, password, passwordSz));
/* invalid params */
AssertIntEQ(BAD_FUNC_ARG, wc_SrpGetVerifier(NULL, v, &vSz));
AssertIntEQ(BAD_FUNC_ARG, wc_SrpGetVerifier(&srp, NULL, &vSz));
AssertIntEQ(BUFFER_E, wc_SrpGetVerifier(&srp, v, &vSz));
/* success */
vSz = sizeof(v);
AssertIntEQ(0, wc_SrpGetVerifier(&srp, v, &vSz));
AssertIntEQ(vSz, sizeof(verifier));
AssertIntEQ(0, XMEMCMP(verifier, v, vSz));
/* invalid params - client side srp */
AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetVerifier(&srp, v, vSz));
wc_SrpTerm(&srp);
AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_SERVER_SIDE));
/* invalid params */
AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetVerifier(NULL, v, vSz));
AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetVerifier(&srp, NULL, vSz));
/* success */
AssertIntEQ(0, wc_SrpSetVerifier(&srp, v, vSz));
wc_SrpTerm(&srp);
}
static void test_SrpGenPublic(void)
{
Srp srp;
byte public[64];
word32 publicSz = 0;
AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE));
/* invalid call order */
AssertIntEQ(SRP_CALL_ORDER_E, wc_SrpGenPublic(&srp, public, &publicSz));
/* fix call order */
AssertIntEQ(0, wc_SrpSetUsername(&srp, username, usernameSz));
AssertIntEQ(0, wc_SrpSetParams(&srp, N, sizeof(N),
g, sizeof(g),
salt, sizeof(salt)));
/* invalid params */
AssertIntEQ(BAD_FUNC_ARG, wc_SrpGenPublic(NULL, public, &publicSz));
AssertIntEQ(BAD_FUNC_ARG, wc_SrpGenPublic(&srp, NULL, &publicSz));
AssertIntEQ(BAD_FUNC_ARG, wc_SrpGenPublic(&srp, public, NULL));
AssertIntEQ(BUFFER_E, wc_SrpGenPublic(&srp, public, &publicSz));
/* success */
publicSz = sizeof(public);
AssertIntEQ(0, wc_SrpGenPublic(&srp, NULL, NULL));
AssertIntEQ(0, wc_SrpSetPrivate(&srp, a, sizeof(a)));
AssertIntEQ(0, wc_SrpGenPublic(&srp, public, &publicSz));
AssertIntEQ(publicSz, sizeof(A));
AssertIntEQ(0, XMEMCMP(public, A, publicSz));
wc_SrpTerm(&srp);
AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_SERVER_SIDE));
AssertIntEQ(0, wc_SrpSetUsername(&srp, username, usernameSz));
AssertIntEQ(0, wc_SrpSetParams(&srp, N, sizeof(N),
g, sizeof(g),
salt, sizeof(salt)));
/* invalid call order */
AssertIntEQ(SRP_CALL_ORDER_E, wc_SrpGenPublic(&srp, public, &publicSz));
/* fix call order */
AssertIntEQ(0, wc_SrpSetVerifier(&srp, verifier, sizeof(verifier)));
/* success */
AssertIntEQ(0, wc_SrpGenPublic(&srp, NULL, NULL));
AssertIntEQ(0, wc_SrpSetPrivate(&srp, b, sizeof(b)));
AssertIntEQ(0, wc_SrpGenPublic(&srp, public, &publicSz));
AssertIntEQ(publicSz, sizeof(B));
AssertIntEQ(0, XMEMCMP(public, B, publicSz));
wc_SrpTerm(&srp);
}
#endif
void SrpTest(void)
@ -127,5 +283,7 @@ void SrpTest(void)
test_SrpInit();
test_SrpSetUsername();
test_SrpSetParams();
test_SrpSetPassword();
test_SrpGenPublic();
#endif
}

View File

@ -27,8 +27,8 @@
#define Fail(description, result) do { \
printf("\nERROR - %s line %d failed with:", __FILE__, __LINE__); \
printf("\n\n test: "); printf description; \
printf("\n\n result: "); printf result; \
printf("\n expected: "); printf description; \
printf("\n result: "); printf result; printf("\n\n"); \
abort(); \
} while(0)

View File

@ -28,6 +28,7 @@
#ifdef WOLFCRYPT_HAVE_SRP
#include <wolfssl/wolfcrypt/srp.h>
#include <wolfssl/wolfcrypt/random.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
static int SrpHashInit(SrpHash* hash, int type)
@ -218,21 +219,20 @@ void wc_SrpTerm(Srp* srp)
}
}
int wc_SrpSetUsername(Srp* srp, const char* user)
int wc_SrpSetUsername(Srp* srp, const byte* username, word32 size)
{
if (!srp || !user)
if (!srp || !username)
return BAD_FUNC_ARG;
srp->user = (byte*)XMALLOC(XSTRLEN(user), NULL, DYNAMIC_TYPE_SRP);
srp->user = (byte*)XMALLOC(size, NULL, DYNAMIC_TYPE_SRP);
if (srp->user == NULL)
return MEMORY_E;
srp->userSz = (word32) XSTRLEN(user);
XMEMCPY(srp->user, user, srp->userSz);
srp->userSz = size;
XMEMCPY(srp->user, username, srp->userSz);
return 0;
}
int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz,
const byte* g, word32 gSz,
const byte* salt, word32 saltSz)
@ -240,11 +240,15 @@ int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz,
SrpHash hash;
byte digest1[SRP_MAX_DIGEST_SIZE];
byte digest2[SRP_MAX_DIGEST_SIZE];
byte pad = 0;
int i, j, r;
if (!srp || !srp->user || !N || !g || !salt)
if (!srp || !N || !g || !salt || nSz < gSz)
return BAD_FUNC_ARG;
if (!srp->user)
return SRP_CALL_ORDER_E;
/* Set N */
if (mp_read_unsigned_bin(&srp->N, N, nSz) != MP_OKAY)
return MP_READ_E;
@ -269,6 +273,8 @@ int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz,
/* Set k = H(N, g) */
r = SrpHashInit(&hash, srp->type);
if (!r) r = SrpHashUpdate(&hash, (byte*) N, nSz);
for (i = 0; (word32)i < nSz - gSz; i++)
SrpHashUpdate(&hash, &pad, 1);
if (!r) r = SrpHashUpdate(&hash, (byte*) g, gSz);
if (!r) r = SrpHashFinal(&hash, srp->k);
@ -307,9 +313,12 @@ int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size)
byte digest[SRP_MAX_DIGEST_SIZE];
int r;
if (!srp || !srp->user || !password || srp->side != SRP_CLIENT_SIDE)
if (!srp || !password || srp->side != SRP_CLIENT_SIDE)
return BAD_FUNC_ARG;
if (!srp->salt)
return SRP_CALL_ORDER_E;
/* digest = H(username | ':' | password) */
r = SrpHashInit(&hash, srp->type);
if (!r) r = SrpHashUpdate(&hash, srp->user, srp->userSz);
@ -341,13 +350,16 @@ int wc_SrpGetVerifier(Srp* srp, byte* verifier, word32* size)
if (!srp || !verifier || !size || srp->side != SRP_CLIENT_SIDE)
return BAD_FUNC_ARG;
if (mp_iszero(&srp->specific.client.x))
return SRP_CALL_ORDER_E;
r = mp_init(&v);
/* v = g ^ x % N */
if (!r) r = mp_exptmod(&srp->g, &srp->specific.client.x, &srp->N, &v);
if (!r) r = (int)*size < mp_unsigned_bin_size(&v) ? BUFFER_E : MP_OKAY;
if (!r) r = *size < (word32)mp_unsigned_bin_size(&v) ? BUFFER_E : MP_OKAY;
if (!r) r = mp_to_unsigned_bin(&v, verifier);
if (!r) *size = mp_unsigned_bin_size(&srp->specific.server.v);
if (!r) *size = mp_unsigned_bin_size(&v);
mp_clear(&v);
@ -366,4 +378,107 @@ int wc_SrpSetVerifier(Srp* srp, const byte* verifier, word32 size)
return 0;
}
int wc_SrpSetPrivate(Srp* srp, const byte* private, word32 size) {
if (!srp || !private || !size)
return BAD_FUNC_ARG;
return mp_read_unsigned_bin(srp->type == SRP_CLIENT_SIDE
? &srp->specific.client.a
: &srp->specific.server.b, private, size);
}
static int wc_SrpGenPrivate(Srp* srp, byte* private, word32 size) {
RNG rng;
int r = wc_InitRng(&rng);
if (!r) r = wc_RNG_GenerateBlock(&rng, private, size);
if (!r) r = wc_SrpSetPrivate(srp, private, size);
if (!r) wc_FreeRng(&rng);
return r;
}
int wc_SrpGenPublic(Srp* srp, byte* public, word32* size)
{
byte* buf;
word32 len;
int r = 0;
if (!srp || (!public && size) || (public && !size))
return BAD_FUNC_ARG;
if (srp->side == SRP_CLIENT_SIDE && mp_iszero(&srp->N))
return SRP_CALL_ORDER_E;
if (srp->side == SRP_SERVER_SIDE && (mp_iszero(&srp->N) ||
mp_iszero(&srp->specific.server.v)))
return SRP_CALL_ORDER_E;
len = mp_unsigned_bin_size(&srp->N);
if (size && *size < len)
return BUFFER_E;
buf = public ? public : (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_SRP);
if (!buf)
return MEMORY_E;
if (srp->side == SRP_CLIENT_SIDE) {
/* a = random() */
if (mp_iszero(&srp->specific.client.a))
r = wc_SrpGenPrivate(srp, buf, len);
/* A = g ^ a % N */
if (!r) r = mp_exptmod(&srp->g, &srp->specific.client.a,
&srp->N, &srp->specific.client.A);
/* extract public key to buffer */
XMEMSET(buf, 0, len);
if (!r) r = mp_to_unsigned_bin(&srp->specific.client.A, buf);
if (!r) len = mp_unsigned_bin_size(&srp->specific.client.A);
/* Client proof = H( H(N) ^ H(g) | H(user) | salt | A) */
if (!r) r = SrpHashUpdate(&srp->client_proof, buf, len);
/* Server proof = H(A) */
if (!r) r = SrpHashUpdate(&srp->server_proof, buf, len);
} else {
mp_int i, j;
if (mp_init_multi(&i, &j, 0, 0, 0, 0) == MP_OKAY) {
/* b = random() */
if (mp_iszero(&srp->specific.server.b))
r = wc_SrpGenPrivate(srp, buf, len);
/* B = (k * v + (g ^ b % N)) % N */
if (!r) r = mp_read_unsigned_bin(&i, srp->k,SrpHashSize(srp->type));
if (!r) r = mp_exptmod(&srp->g, &srp->specific.server.b,
&srp->N, &srp->specific.server.B);
if (!r) r = mp_mul(&i, &srp->specific.server.v, &j);
if (!r) r = mp_add(&j, &srp->specific.server.B, &i);
if (!r) r = mp_mod(&i, &srp->N, &srp->specific.server.B);
/* extract public key to buffer */
XMEMSET(buf, 0, len);
if (!r) r = mp_to_unsigned_bin(&srp->specific.server.B, buf);
if (!r) len = mp_unsigned_bin_size(&srp->specific.server.B);
/* Client proof = H( H(N) ^ H(g) | H(user) | salt | A) */
if (!r) r = SrpHashUpdate(&srp->client_proof, buf, len);
/* Server proof = H(A) */
if (!r) r = SrpHashUpdate(&srp->server_proof, buf, len);
mp_clear(&i); mp_clear(&j);
}
}
if (public)
*size = len;
else
XFREE(buf, NULL, DYNAMIC_TYPE_SRP);
return r;
}
#endif /* WOLFCRYPT_HAVE_SRP */

View File

@ -151,6 +151,8 @@ enum {
ECC_INF_E = -215, /* ECC point infinity error */
ECC_PRIV_KEY_E = -216, /* ECC private key not valid error */
SRP_CALL_ORDER_E = -217, /* SRP function called in the wrong order. */
MIN_CODE_E = -300 /* errors -101 - -299 */
};
@ -163,5 +165,3 @@ WOLFSSL_API const char* wc_GetErrorString(int error);
} /* extern "C" */
#endif
#endif /* WOLF_CRYPT_ERROR_H */

View File

@ -119,7 +119,7 @@ typedef struct {
WOLFSSL_API int wc_SrpInit(Srp* srp, byte type, byte side);
WOLFSSL_API void wc_SrpTerm(Srp* srp);
WOLFSSL_API int wc_SrpSetUsername(Srp* srp, const char* user);
WOLFSSL_API int wc_SrpSetUsername(Srp* srp, const byte* username, word32 size);
WOLFSSL_API int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz,
const byte* g, word32 gSz,
@ -131,6 +131,10 @@ WOLFSSL_API int wc_SrpSetVerifier(Srp* srp, const byte* verifier, word32 size);
WOLFSSL_API int wc_SrpGetVerifier(Srp* srp, byte* verifier, word32* size);
WOLFSSL_API int wc_SrpSetPrivate(Srp* srp, const byte* private, word32 size);
WOLFSSL_API int wc_SrpGenPublic(Srp* srp, byte* public, word32* size);
#ifdef __cplusplus
} /* extern "C" */
#endif