diff --git a/wolfcrypt/src/error.c b/wolfcrypt/src/error.c index 7d1d5ebe7..37b78422a 100644 --- a/wolfcrypt/src/error.c +++ b/wolfcrypt/src/error.c @@ -328,6 +328,15 @@ const char* wc_GetErrorString(int error) case ECC_PRIV_KEY_E: return " ECC private key is not valid error"; + case SRP_CALL_ORDER_E: + return "SRP function called in the wrong order error"; + + case SRP_VERIFY_E: + return "SRP proof verification error"; + + case SRP_BAD_KEY_E: + return "SRP bad key values error"; + default: return "unknown error number"; diff --git a/wolfcrypt/src/srp.c b/wolfcrypt/src/srp.c index 66e7e7fda..6e8b22d2f 100644 --- a/wolfcrypt/src/srp.c +++ b/wolfcrypt/src/srp.c @@ -32,40 +32,7 @@ #include /** Computes the session key using the Mask Generation Function 1. */ -static int wc_SrpSetK(Srp* srp, byte* secret, word32 size); - -#include -static inline void LogHex(byte* data, word32 length) -{ - #define LINE_LEN 16 - - word32 i; - - printf("\t"); - - if (!data) { - printf("NULL\n"); - return; - } - - for (i = 0; i < LINE_LEN; i++) { - if (i < length) - printf("%02x ", data[i]); - else - printf(" "); - } - - printf("| "); - - for (i = 0; i < LINE_LEN; i++) - if (i < length) - printf("%c", 31 < data[i] && data[i] < 127 ? data[i] : '.'); - - printf("\n"); - - if (length > LINE_LEN) - LogHex(data + LINE_LEN, length - LINE_LEN); -} +static int wc_SrpSetKey(Srp* srp, byte* secret, word32 size); static int SrpHashInit(SrpHash* hash, SrpType type) { @@ -216,7 +183,7 @@ int wc_SrpInit(Srp* srp, SrpType type, SrpSide side) srp->user = NULL; srp->userSz = 0; srp->key = NULL; srp->keySz = 0; - srp->keyGenFunc_cb = wc_SrpSetK; + srp->keyGenFunc_cb = wc_SrpSetKey; return 0; } @@ -273,10 +240,16 @@ int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, if (mp_read_unsigned_bin(&srp->N, N, nSz) != MP_OKAY) return MP_READ_E; + if (mp_count_bits(&srp->N) < SRP_DEFAULT_MIN_BITS) + return BAD_FUNC_ARG; + /* Set g */ if (mp_read_unsigned_bin(&srp->g, g, gSz) != MP_OKAY) return MP_READ_E; + if (mp_cmp(&srp->N, &srp->g) != MP_GT) + return BAD_FUNC_ARG; + /* Set salt */ if (srp->salt) { XMEMSET(srp->salt, 0, srp->saltSz); @@ -397,13 +370,23 @@ int wc_SrpSetVerifier(Srp* srp, const byte* verifier, word32 size) int wc_SrpSetPrivate(Srp* srp, const byte* private, word32 size) { + mp_int p; + int r; + if (!srp || !private || !size) return BAD_FUNC_ARG; if (mp_iszero(&srp->auth)) return SRP_CALL_ORDER_E; - return mp_read_unsigned_bin(&srp->priv, private, size); + r = mp_init(&p); + if (!r) r = mp_read_unsigned_bin(&p, private, size); + if (!r) r = mp_mod(&p, &srp->N, &srp->priv); + if (!r) r = mp_iszero(&srp->priv) ? SRP_BAD_KEY_E : 0; + + mp_clear(&p); + + return r; } /** Generates random data using wolfcrypt RNG. */ @@ -452,6 +435,7 @@ int wc_SrpGetPublic(Srp* srp, byte* public, word32* size) if (mp_init_multi(&i, &j, 0, 0, 0, 0) == MP_OKAY) { if (!r) r = mp_read_unsigned_bin(&i, srp->k,SrpHashSize(srp->type)); + if (!r) r = mp_iszero(&i) ? SRP_BAD_KEY_E : 0; if (!r) r = mp_exptmod(&srp->g, &srp->priv, &srp->N, &pubkey); if (!r) r = mp_mulmod(&i, &srp->auth, &srp->N, &j); if (!r) r = mp_add(&j, &pubkey, &i); @@ -470,7 +454,7 @@ int wc_SrpGetPublic(Srp* srp, byte* public, word32* size) return r; } -static int wc_SrpSetK(Srp* srp, byte* secret, word32 size) +static int wc_SrpSetKey(Srp* srp, byte* secret, word32 size) { SrpHash hash; byte digest[SRP_MAX_DIGEST_SIZE]; @@ -566,11 +550,15 @@ int wc_SrpComputeKey(Srp* srp, byte* clientPubKey, word32 clientPubKeySz, /* building s (secret) */ if (!r && srp->side == SRP_CLIENT_SIDE) { - /* temp1 = B - k * v */ + + /* temp1 = B - k * v; rejects k == 0, B == 0 and B >= N. */ r = mp_read_unsigned_bin(&temp1, srp->k, digestSz); + if (!r) r = mp_iszero(&temp1) ? SRP_BAD_KEY_E : 0; if (!r) r = mp_exptmod(&srp->g, &srp->auth, &srp->N, &temp2); if (!r) r = mp_mulmod(&temp1, &temp2, &srp->N, &s); if (!r) r = mp_read_unsigned_bin(&temp2, serverPubKey, serverPubKeySz); + if (!r) r = mp_iszero(&temp2) ? SRP_BAD_KEY_E : 0; + if (!r) r = mp_cmp(&temp2, &srp->N) != MP_LT ? SRP_BAD_KEY_E : 0; if (!r) r = mp_sub(&temp2, &s, &temp1); /* temp2 = a + u * x */ @@ -584,10 +572,18 @@ int wc_SrpComputeKey(Srp* srp, byte* clientPubKey, word32 clientPubKeySz, /* temp1 = v ^ u % N */ r = mp_exptmod(&srp->auth, &u, &srp->N, &temp1); - /* temp2 = A * temp1 % N */ + /* temp2 = A * temp1 % N; rejects A == 0, A >= N */ if (!r) r = mp_read_unsigned_bin(&s, clientPubKey, clientPubKeySz); + if (!r) r = mp_iszero(&s) ? SRP_BAD_KEY_E : 0; + if (!r) r = mp_cmp(&s, &srp->N) != MP_LT ? SRP_BAD_KEY_E : 0; if (!r) r = mp_mulmod(&s, &temp1, &srp->N, &temp2); + /* rejects A * v ^ u % N >= 1, A * v ^ u % N == -1 % N */ + if (!r) r = mp_read_unsigned_bin(&temp1, (const byte*)"\001", 1); + if (!r) r = mp_cmp(&temp2, &temp1) != MP_GT ? SRP_BAD_KEY_E : 0; + if (!r) r = mp_sub(&srp->N, &temp1, &s); + if (!r) r = mp_cmp(&temp2, &s) == MP_EQ ? SRP_BAD_KEY_E : 0; + /* secret = temp2 * b % N */ if (!r) r = mp_exptmod(&temp2, &srp->priv, &srp->N, &s); } @@ -596,8 +592,6 @@ int wc_SrpComputeKey(Srp* srp, byte* clientPubKey, word32 clientPubKeySz, if (!r) r = mp_to_unsigned_bin(&s, secret); if (!r) r = srp->keyGenFunc_cb(srp, secret, mp_unsigned_bin_size(&s)); - printf("key\n"); - LogHex(srp->key, srp->keySz); /* updating client proof = H( H(N) ^ H(g) | H(user) | salt | A | B | K) */ diff --git a/wolfssl/wolfcrypt/error-crypt.h b/wolfssl/wolfcrypt/error-crypt.h index 84714e462..340d1db75 100644 --- a/wolfssl/wolfcrypt/error-crypt.h +++ b/wolfssl/wolfcrypt/error-crypt.h @@ -153,6 +153,7 @@ enum { SRP_CALL_ORDER_E = -217, /* SRP function called in the wrong order. */ SRP_VERIFY_E = -218, /* SRP proof verification failed. */ + SRP_BAD_KEY_E = -219, /* SRP bad ephemeral values. */ MIN_CODE_E = -300 /* errors -101 - -299 */ }; diff --git a/wolfssl/wolfcrypt/srp.h b/wolfssl/wolfcrypt/srp.h index ba917d2ad..3992a07ea 100644 --- a/wolfssl/wolfcrypt/srp.h +++ b/wolfssl/wolfcrypt/srp.h @@ -47,6 +47,9 @@ #error "You have to have some kind of SHA hash if you want to use SRP." #endif +/* Set the minimum number of bits acceptable in an SRP modulus */ +#define SRP_DEFAULT_MIN_BITS 512 + /** * SRP side, client or server. */