static int _Transform(Sha512* sha512) { const word64* K = K512; word32 j; word64 T[8]; #ifdef WOLFSSL_SMALL_STACK word64* W; W = (word64*) XMALLOC(sizeof(word64) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (W == NULL) return MEMORY_E; #else word64 W[16]; #endif /* Copy digest to working vars */ XMEMCPY(T, sha512->digest, sizeof(T)); #ifdef USE_SLOW_SHA2 /* over twice as small, but 50% slower */ /* 80 operations, not unrolled */ for (j = 0; j < 80; j += 16) { int m; for (m = 0; m < 16; m++) { /* braces needed here for macros {} */ R(m); } } #else /* 80 operations, partially loop unrolled */ for (j = 0; j < 80; j += 16) { R( 0); R( 1); R( 2); R( 3); R( 4); R( 5); R( 6); R( 7); R( 8); R( 9); R(10); R(11); R(12); R(13); R(14); R(15); } #endif /* USE_SLOW_SHA2 */ /* Add the working vars back into digest */ sha512->digest[0] += a(0); sha512->digest[1] += b(0); sha512->digest[2] += c(0); sha512->digest[3] += d(0); sha512->digest[4] += e(0); sha512->digest[5] += f(0); sha512->digest[6] += g(0); sha512->digest[7] += h(0); /* Wipe variables */ ForceZero(W, sizeof(word64) * 16); ForceZero(T, sizeof(T)); #ifdef WOLFSSL_SMALL_STACK XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return 0; }
/* generate an ed25519 key pair. * returns 0 on success */ int wc_ed25519_make_key(WC_RNG* rng, int keySz, ed25519_key* key) { byte az[ED25519_PRV_KEY_SIZE]; int ret; ge_p3 A; if (rng == NULL || key == NULL) return BAD_FUNC_ARG; /* ed25519 has 32 byte key sizes */ if (keySz != ED25519_KEY_SIZE) return BAD_FUNC_ARG; ret = wc_RNG_GenerateBlock(rng, key->k, ED25519_KEY_SIZE); if (ret != 0) return ret; ret = wc_Sha512Hash(key->k, ED25519_KEY_SIZE, az); if (ret != 0) { ForceZero(key->k, ED25519_KEY_SIZE); return ret; } /* apply clamp */ az[0] &= 248; az[31] &= 63; /* same than az[31] &= 127 because of az[31] |= 64 */ az[31] |= 64; ge_scalarmult_base(&A, az); ge_p3_tobytes(key->p, &A); /* put public key after private key, on the same buffer */ XMEMMOVE(key->k + ED25519_KEY_SIZE, key->p, ED25519_PUB_KEY_SIZE); return ret; }
/* clear memory of key */ void wc_ed25519_free(ed25519_key* key) { if (key == NULL) return; ForceZero(key, sizeof(ed25519_key)); }
int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size) { SrpHash hash; byte digest[SRP_MAX_DIGEST_SIZE]; word32 digestSz; int r; if (!srp || !password || srp->side != SRP_CLIENT_SIDE) return BAD_FUNC_ARG; if (!srp->salt) return SRP_CALL_ORDER_E; digestSz = SrpHashSize(srp->type); /* digest = H(username | ':' | password) */ r = SrpHashInit(&hash, srp->type); if (!r) r = SrpHashUpdate(&hash, srp->user, srp->userSz); if (!r) r = SrpHashUpdate(&hash, (const byte*) ":", 1); if (!r) r = SrpHashUpdate(&hash, password, size); if (!r) r = SrpHashFinal(&hash, digest); /* digest = H(salt | H(username | ':' | password)) */ if (!r) r = SrpHashInit(&hash, srp->type); if (!r) r = SrpHashUpdate(&hash, srp->salt, srp->saltSz); if (!r) r = SrpHashUpdate(&hash, digest, digestSz); if (!r) r = SrpHashFinal(&hash, digest); /* Set x (private key) */ if (!r) r = mp_read_unsigned_bin(&srp->auth, digest, digestSz); ForceZero(digest, SRP_MAX_DIGEST_SIZE); return r; }
int wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out, word32 outLen, RsaKey* key) { int plainLen; byte* tmp; byte* pad = 0; tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA); if (tmp == NULL) { return MEMORY_E; } XMEMCPY(tmp, in, inLen); if ( (plainLen = wc_RsaSSL_VerifyInline(tmp, inLen, &pad, key) ) < 0) { XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); return plainLen; } if (plainLen > (int)outLen) plainLen = BAD_FUNC_ARG; else XMEMCPY(out, pad, plainLen); ForceZero(tmp, inLen); XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); return plainLen; }
int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, word32 outLen, RsaKey* key) { int plainLen; byte* tmp; byte* pad = 0; #ifdef HAVE_CAVIUM if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) return CaviumRsaPrivateDecrypt(in, inLen, out, outLen, key); #endif tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA); if (tmp == NULL) { return MEMORY_E; } XMEMCPY(tmp, in, inLen); if ( (plainLen = wc_RsaPrivateDecryptInline(tmp, inLen, &pad, key) ) < 0) { XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); return plainLen; } if (plainLen > (int)outLen) plainLen = BAD_FUNC_ARG; else XMEMCPY(out, pad, plainLen); ForceZero(tmp, inLen); XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); return plainLen; }
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */ static int Hash_gen(DRBG* drbg, byte* out, word32 outSz, const byte* V) { byte data[DRBG_SEED_LEN]; int i; int len; word32 checkBlock; Sha256 sha; byte digest[SHA256_DIGEST_SIZE]; /* Special case: outSz is 0 and out is NULL. wc_Generate a block to save for * the continuous test. */ if (outSz == 0) outSz = 1; len = (outSz / OUTPUT_BLOCK_LEN) + ((outSz % OUTPUT_BLOCK_LEN) ? 1 : 0); XMEMCPY(data, V, sizeof(data)); for (i = 0; i < len; i++) { if (wc_InitSha256(&sha) != 0 || wc_Sha256Update(&sha, data, sizeof(data)) != 0 || wc_Sha256Final(&sha, digest) != 0) { return DRBG_FAILURE; } XMEMCPY(&checkBlock, digest, sizeof(word32)); if (drbg->reseedCtr > 1 && checkBlock == drbg->lastBlock) { if (drbg->matchCount == 1) { return DRBG_CONT_FAILURE; } else { if (i == len) { len++; } drbg->matchCount = 1; } } else { drbg->matchCount = 0; drbg->lastBlock = checkBlock; } if (out != NULL) { if (outSz >= OUTPUT_BLOCK_LEN) { XMEMCPY(out, digest, OUTPUT_BLOCK_LEN); outSz -= OUTPUT_BLOCK_LEN; out += OUTPUT_BLOCK_LEN; array_add_one(data, DRBG_SEED_LEN); } else if (out != NULL && outSz != 0) { XMEMCPY(out, digest, outSz); outSz = 0; } } } ForceZero(data, sizeof(data)); return DRBG_SUCCESS; }
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */ static int Hash_df(DRBG* drbg, byte* out, word32 outSz, byte type, const byte* inA, word32 inASz, const byte* inB, word32 inBSz) { byte ctr; int i; int len; word32 bits = (outSz * 8); /* reverse byte order */ Sha256 sha; byte digest[SHA256_DIGEST_SIZE]; (void)drbg; #ifdef LITTLE_ENDIAN_ORDER bits = ByteReverseWord32(bits); #endif len = (outSz / OUTPUT_BLOCK_LEN) + ((outSz % OUTPUT_BLOCK_LEN) ? 1 : 0); for (i = 0, ctr = 1; i < len; i++, ctr++) { if (wc_InitSha256(&sha) != 0) return DRBG_FAILURE; if (wc_Sha256Update(&sha, &ctr, sizeof(ctr)) != 0) return DRBG_FAILURE; if (wc_Sha256Update(&sha, (byte*)&bits, sizeof(bits)) != 0) return DRBG_FAILURE; /* churning V is the only string that doesn't have the type added */ if (type != drbgInitV) if (wc_Sha256Update(&sha, &type, sizeof(type)) != 0) return DRBG_FAILURE; if (wc_Sha256Update(&sha, inA, inASz) != 0) return DRBG_FAILURE; if (inB != NULL && inBSz > 0) if (wc_Sha256Update(&sha, inB, inBSz) != 0) return DRBG_FAILURE; if (wc_Sha256Final(&sha, digest) != 0) return DRBG_FAILURE; if (outSz > OUTPUT_BLOCK_LEN) { XMEMCPY(out, digest, OUTPUT_BLOCK_LEN); outSz -= OUTPUT_BLOCK_LEN; out += OUTPUT_BLOCK_LEN; } else { XMEMCPY(out, digest, outSz); } } ForceZero(digest, sizeof(digest)); return DRBG_SUCCESS; }
void wc_SrpTerm(Srp* srp) { if (srp) { mp_clear(&srp->N); mp_clear(&srp->g); mp_clear(&srp->auth); mp_clear(&srp->priv); ForceZero(srp->salt, srp->saltSz); XFREE(srp->salt, NULL, DYNAMIC_TYPE_SRP); ForceZero(srp->user, srp->userSz); XFREE(srp->user, NULL, DYNAMIC_TYPE_SRP); ForceZero(srp->key, srp->keySz); XFREE(srp->key, NULL, DYNAMIC_TYPE_SRP); ForceZero(srp, sizeof(Srp)); } }
static int InitOcspEntry(OcspEntry* entry, OcspRequest* request) { WOLFSSL_ENTER("InitOcspEntry"); ForceZero(entry, sizeof(OcspEntry)); XMEMCPY(entry->issuerHash, request->issuerHash, OCSP_DIGEST_SIZE); XMEMCPY(entry->issuerKeyHash, request->issuerKeyHash, OCSP_DIGEST_SIZE); return 0; }
int InitOCSP(WOLFSSL_OCSP* ocsp, WOLFSSL_CERT_MANAGER* cm) { WOLFSSL_ENTER("InitOCSP"); ForceZero(ocsp, sizeof(WOLFSSL_OCSP)); if (InitMutex(&ocsp->ocspLock) != 0) return BAD_MUTEX_E; ocsp->cm = cm; return 0; }
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */ static int Hash_DRBG_Reseed(DRBG* drbg, const byte* entropy, word32 entropySz) { byte seed[DRBG_SEED_LEN]; if (Hash_df(drbg, seed, sizeof(seed), drbgReseed, drbg->V, sizeof(drbg->V), entropy, entropySz) != DRBG_SUCCESS) { return DRBG_FAILURE; } XMEMCPY(drbg->V, seed, sizeof(drbg->V)); ForceZero(seed, sizeof(seed)); if (Hash_df(drbg, drbg->C, sizeof(drbg->C), drbgInitC, drbg->V, sizeof(drbg->V), NULL, 0) != DRBG_SUCCESS) { return DRBG_FAILURE; } drbg->reseedCtr = 1; drbg->lastBlock = 0; drbg->matchCount = 0; return DRBG_SUCCESS; }
int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, const byte* g, word32 gSz, const byte* salt, word32 saltSz) { SrpHash hash; byte digest1[SRP_MAX_DIGEST_SIZE]; byte digest2[SRP_MAX_DIGEST_SIZE]; byte pad = 0; int i, j, r; 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; if (mp_count_bits(&srp->N) < SRP_MODULUS_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) { ForceZero(srp->salt, srp->saltSz); XFREE(srp->salt, srp->heap, DYNAMIC_TYPE_SRP); } srp->salt = (byte*)XMALLOC(saltSz, srp->heap, DYNAMIC_TYPE_SRP); if (srp->salt == NULL) return MEMORY_E; XMEMCPY(srp->salt, salt, saltSz); srp->saltSz = saltSz; /* 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); /* update client proof */ /* digest1 = H(N) */ if (!r) r = SrpHashInit(&hash, srp->type); if (!r) r = SrpHashUpdate(&hash, (byte*) N, nSz); if (!r) r = SrpHashFinal(&hash, digest1); /* digest2 = H(g) */ if (!r) r = SrpHashInit(&hash, srp->type); if (!r) r = SrpHashUpdate(&hash, (byte*) g, gSz); if (!r) r = SrpHashFinal(&hash, digest2); /* digest1 = H(N) ^ H(g) */ if (r == 0) { for (i = 0, j = SrpHashSize(srp->type); i < j; i++) digest1[i] ^= digest2[i]; } /* digest2 = H(user) */ if (!r) r = SrpHashInit(&hash, srp->type); if (!r) r = SrpHashUpdate(&hash, srp->user, srp->userSz); if (!r) r = SrpHashFinal(&hash, digest2); /* client proof = H( H(N) ^ H(g) | H(user) | salt) */ if (!r) r = SrpHashUpdate(&srp->client_proof, digest1, j); if (!r) r = SrpHashUpdate(&srp->client_proof, digest2, j); if (!r) r = SrpHashUpdate(&srp->client_proof, salt, saltSz); return r; }
void wc_bigint_zero(WC_BIGINT* a) { if (a && a->buf) { ForceZero(a->buf, a->len); } }
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */ static int Hash_gen(DRBG* drbg, byte* out, word32 outSz, const byte* V) { int ret = DRBG_FAILURE; byte data[DRBG_SEED_LEN]; int i; int len; word32 checkBlock; Sha256 sha; DECLARE_VAR(digest, byte, SHA256_DIGEST_SIZE, drbg->heap); /* Special case: outSz is 0 and out is NULL. wc_Generate a block to save for * the continuous test. */ if (outSz == 0) outSz = 1; len = (outSz / OUTPUT_BLOCK_LEN) + ((outSz % OUTPUT_BLOCK_LEN) ? 1 : 0); XMEMCPY(data, V, sizeof(data)); for (i = 0; i < len; i++) { #ifdef WOLFSSL_ASYNC_CRYPT ret = wc_InitSha256_ex(&sha, drbg->heap, drbg->devId); #else ret = wc_InitSha256(&sha); #endif if (ret == 0) ret = wc_Sha256Update(&sha, data, sizeof(data)); if (ret == 0) ret = wc_Sha256Final(&sha, digest); wc_Sha256Free(&sha); if (ret == 0) { XMEMCPY(&checkBlock, digest, sizeof(word32)); if (drbg->reseedCtr > 1 && checkBlock == drbg->lastBlock) { if (drbg->matchCount == 1) { return DRBG_CONT_FAILURE; } else { if (i == len) { len++; } drbg->matchCount = 1; } } else { drbg->matchCount = 0; drbg->lastBlock = checkBlock; } if (out != NULL && outSz != 0) { if (outSz >= OUTPUT_BLOCK_LEN) { XMEMCPY(out, digest, OUTPUT_BLOCK_LEN); outSz -= OUTPUT_BLOCK_LEN; out += OUTPUT_BLOCK_LEN; array_add_one(data, DRBG_SEED_LEN); } else { XMEMCPY(out, digest, outSz); outSz = 0; } } } } ForceZero(data, sizeof(data)); FREE_VAR(digest, drbg->heap); return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE; }
/* Returns: DRBG_SUCCESS or DRBG_FAILURE */ static int Hash_df(DRBG* drbg, byte* out, word32 outSz, byte type, const byte* inA, word32 inASz, const byte* inB, word32 inBSz) { int ret = DRBG_FAILURE; byte ctr; int i; int len; word32 bits = (outSz * 8); /* reverse byte order */ Sha256 sha; DECLARE_VAR(digest, byte, SHA256_DIGEST_SIZE, drbg->heap); (void)drbg; #ifdef WOLFSSL_ASYNC_CRYPT if (digest == NULL) return DRBG_FAILURE; #endif #ifdef LITTLE_ENDIAN_ORDER bits = ByteReverseWord32(bits); #endif len = (outSz / OUTPUT_BLOCK_LEN) + ((outSz % OUTPUT_BLOCK_LEN) ? 1 : 0); for (i = 0, ctr = 1; i < len; i++, ctr++) { #ifdef WOLFSSL_ASYNC_CRYPT ret = wc_InitSha256_ex(&sha, drbg->heap, drbg->devId); #else ret = wc_InitSha256(&sha); #endif if (ret != 0) break; if (ret == 0) ret = wc_Sha256Update(&sha, &ctr, sizeof(ctr)); if (ret == 0) ret = wc_Sha256Update(&sha, (byte*)&bits, sizeof(bits)); if (ret == 0) { /* churning V is the only string that doesn't have the type added */ if (type != drbgInitV) ret = wc_Sha256Update(&sha, &type, sizeof(type)); } if (ret == 0) ret = wc_Sha256Update(&sha, inA, inASz); if (ret == 0) { if (inB != NULL && inBSz > 0) ret = wc_Sha256Update(&sha, inB, inBSz); } if (ret == 0) ret = wc_Sha256Final(&sha, digest); wc_Sha256Free(&sha); if (ret == 0) { if (outSz > OUTPUT_BLOCK_LEN) { XMEMCPY(out, digest, OUTPUT_BLOCK_LEN); outSz -= OUTPUT_BLOCK_LEN; out += OUTPUT_BLOCK_LEN; } else { XMEMCPY(out, digest, outSz); } } } ForceZero(digest, SHA256_DIGEST_SIZE); FREE_VAR(digest, drbg->heap); return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE; }