/* 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; }
/* in contains the message to sign inlen is the length of the message to sign out is the buffer to write the signature outLen [in/out] input size of out buf output gets set as the final length of out key is the ed25519 key to use when signing return 0 on success */ int wc_ed25519_sign_msg(const byte* in, word32 inlen, byte* out, word32 *outLen, ed25519_key* key) { ge_p3 R; byte nonce[SHA512_DIGEST_SIZE]; byte hram[SHA512_DIGEST_SIZE]; byte az[ED25519_PRV_KEY_SIZE]; Sha512 sha; int ret; /* sanity check on arguments */ if (in == NULL || out == NULL || outLen == NULL || key == NULL) return BAD_FUNC_ARG; /* check and set up out length */ if (*outLen < ED25519_SIG_SIZE) { *outLen = ED25519_SIG_SIZE; return BUFFER_E; } *outLen = ED25519_SIG_SIZE; /* step 1: create nonce to use where nonce is r in r = H(h_b, ... ,h_2b-1,M) */ ret = wc_Sha512Hash(key->k, ED25519_KEY_SIZE, az); if (ret != 0) return ret; /* apply clamp */ az[0] &= 248; az[31] &= 63; /* same than az[31] &= 127 because of az[31] |= 64 */ az[31] |= 64; ret = wc_InitSha512(&sha); if (ret != 0) return ret; ret = wc_Sha512Update(&sha, az + ED25519_KEY_SIZE, ED25519_KEY_SIZE); if (ret != 0) return ret; ret = wc_Sha512Update(&sha, in, inlen); if (ret != 0) return ret; ret = wc_Sha512Final(&sha, nonce); if (ret != 0) return ret; sc_reduce(nonce); /* step 2: computing R = rB where rB is the scalar multiplication of r and B */ ge_scalarmult_base(&R,nonce); ge_p3_tobytes(out,&R); /* step 3: hash R + public key + message getting H(R,A,M) then creating S = (r + H(R,A,M)a) mod l */ ret = wc_InitSha512(&sha); if (ret != 0) return ret; ret = wc_Sha512Update(&sha, out, ED25519_SIG_SIZE/2); if (ret != 0) return ret; ret = wc_Sha512Update(&sha, key->p, ED25519_PUB_KEY_SIZE); if (ret != 0) return ret; ret = wc_Sha512Update(&sha, in, inlen); if (ret != 0) return ret; ret = wc_Sha512Final(&sha, hram); if (ret != 0) return ret; sc_reduce(hram); sc_muladd(out + (ED25519_SIG_SIZE/2), hram, az, nonce); return ret; }
/* Generic Hashing Wrapper */ int wc_Hash(enum wc_HashType hash_type, const byte* data, word32 data_len, byte* hash, word32 hash_len) { int ret = HASH_TYPE_E; /* Default to hash type error */ word32 dig_size; /* Validate hash buffer size */ dig_size = wc_HashGetDigestSize(hash_type); if (hash_len < dig_size) { return BUFFER_E; } /* Suppress possible unused arg if all hashing is disabled */ (void)data; (void)data_len; (void)hash; (void)hash_len; switch(hash_type) { case WC_HASH_TYPE_MD5: #ifndef NO_MD5 ret = wc_Md5Hash(data, data_len, hash); #endif break; case WC_HASH_TYPE_SHA: #ifndef NO_SHA ret = wc_ShaHash(data, data_len, hash); #endif break; case WC_HASH_TYPE_SHA224: #ifdef WOLFSSL_SHA224 ret = wc_Sha224Hash(data, data_len, hash); #endif break; case WC_HASH_TYPE_SHA256: #ifndef NO_SHA256 ret = wc_Sha256Hash(data, data_len, hash); #endif break; case WC_HASH_TYPE_SHA384: #if defined(WOLFSSL_SHA512) && defined(WOLFSSL_SHA384) ret = wc_Sha384Hash(data, data_len, hash); #endif break; case WC_HASH_TYPE_SHA512: #ifdef WOLFSSL_SHA512 ret = wc_Sha512Hash(data, data_len, hash); #endif break; case WC_HASH_TYPE_MD5_SHA: #if !defined(NO_MD5) && !defined(NO_SHA) ret = wc_Md5Hash(data, data_len, hash); if (ret == 0) { ret = wc_ShaHash(data, data_len, &hash[MD5_DIGEST_SIZE]); } #endif break; /* Not Supported */ case WC_HASH_TYPE_MD2: case WC_HASH_TYPE_MD4: case WC_HASH_TYPE_NONE: default: ret = BAD_FUNC_ARG; break; } return ret; }
/* Generic Hashing Wrapper */ int wc_Hash(enum wc_HashType hash_type, const byte* data, word32 data_len, byte* hash, word32 hash_len) { int ret = BAD_FUNC_ARG; word32 dig_size; /* Validate hash buffer size */ dig_size = wc_HashGetDigestSize(hash_type); if (hash_len < dig_size) { return BUFFER_E; } /* Supress possible unused arg if all hashing is disabled */ (void)data; (void)data_len; (void)hash; (void)hash_len; switch(hash_type) { #ifndef NO_MD5 case WC_HASH_TYPE_MD5: ret = wc_Md5Hash(data, data_len, hash); break; #endif #ifndef NO_SHA case WC_HASH_TYPE_SHA: ret = wc_ShaHash(data, data_len, hash); break; #endif #ifndef NO_SHA256 case WC_HASH_TYPE_SHA256: ret = wc_Sha256Hash(data, data_len, hash); break; #endif #ifdef WOLFSSL_SHA512 #ifdef WOLFSSL_SHA384 case WC_HASH_TYPE_SHA384: ret = wc_Sha384Hash(data, data_len, hash); break; #endif /* WOLFSSL_SHA384 */ case WC_HASH_TYPE_SHA512: ret = wc_Sha512Hash(data, data_len, hash); break; #endif /* WOLFSSL_SHA512 */ /* Not Supported */ #ifdef WOLFSSL_MD2 case WC_HASH_TYPE_MD2: #endif #ifndef NO_MD4 case WC_HASH_TYPE_MD4: #endif case WC_HASH_TYPE_NONE: default: WOLFSSL_MSG("wc_Hash: Bad hash type"); ret = BAD_FUNC_ARG; break; } return ret; }