From c5b6d2048305de2a568c2036fca62ed53040d4ed Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Wed, 31 Mar 2021 17:31:52 +0200 Subject: [PATCH] Add more DSA parameters support - Implement wc_DsaParamsDecode and wc_DsaKeyToParamsDer - Don't include NIDs without OpenSSL builds --- wolfcrypt/src/asn.c | 93 +++++++++++++++++++++++++--------- wolfssl/wolfcrypt/asn.h | 5 +- wolfssl/wolfcrypt/asn_public.h | 8 +++ 3 files changed, 82 insertions(+), 24 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index a19529107..a21baf575 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -4708,6 +4708,7 @@ int DsaPublicKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key, int length; int ret = 0; word32 oid; + word32 maxIdx; if (input == NULL || inOutIdx == NULL || key == NULL) return BAD_FUNC_ARG; @@ -4715,10 +4716,11 @@ int DsaPublicKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key, if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; - if (GetInt(&key->p, input, inOutIdx, inSz) < 0 || - GetInt(&key->q, input, inOutIdx, inSz) < 0 || - GetInt(&key->g, input, inOutIdx, inSz) < 0 || - GetInt(&key->y, input, inOutIdx, inSz) < 0 ) + maxIdx = (word32)(*inOutIdx + length); + if (GetInt(&key->p, input, inOutIdx, maxIdx) < 0 || + GetInt(&key->q, input, inOutIdx, maxIdx) < 0 || + GetInt(&key->g, input, inOutIdx, maxIdx) < 0 || + GetInt(&key->y, input, inOutIdx, maxIdx) < 0 ) ret = ASN_DH_KEY_E; if (ret != 0) { @@ -4750,6 +4752,27 @@ int DsaPublicKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key, return ret; } +int wc_DsaParamsDecode(const byte* input, word32* inOutIdx, DsaKey* key, + word32 inSz) +{ + int length; + word32 maxIdx; + + if (input == NULL || inOutIdx == NULL || key == NULL) + return BAD_FUNC_ARG; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + maxIdx = (word32)(*inOutIdx + length); + if (GetInt(&key->p, input, inOutIdx, maxIdx) < 0 || + GetInt(&key->q, input, inOutIdx, maxIdx) < 0 || + GetInt(&key->g, input, inOutIdx, maxIdx) < 0) + return ASN_DH_KEY_E; + + return 0; +} + int DsaPrivateKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key, word32 inSz) @@ -4828,6 +4851,7 @@ int DsaPrivateKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key, static mp_int* GetDsaInt(DsaKey* key, int idx) { + /* Other functions depend on this order. Please don't change it. */ if (idx == 0) return &key->p; if (idx == 1) @@ -4843,11 +4867,11 @@ static mp_int* GetDsaInt(DsaKey* key, int idx) } /* Release Tmp DSA resources */ -static WC_INLINE void FreeTmpDsas(byte** tmps, void* heap) +static WC_INLINE void FreeTmpDsas(byte** tmps, void* heap, int ints) { int i; - for (i = 0; i < DSA_INTS; i++) + for (i = 0; i < ints; i++) XFREE(tmps[i], heap, DYNAMIC_TYPE_DSA); (void)heap; @@ -5047,11 +5071,10 @@ int wc_DsaKeyToPublicDer(DsaKey* key, byte* output, word32 inLen) } #endif /* !HAVE_SELFTEST && (WOLFSSL_KEY_GEN || WOLFSSL_CERT_GEN) */ -/* Convert private DsaKey key to DER format, write to output (inLen), - return bytes written */ -int wc_DsaKeyToDer(DsaKey* key, byte* output, word32 inLen) +static int DsaKeyIntsToDer(DsaKey* key, byte* output, word32 inLen, + int ints, int includeVersion) { - word32 seqSz, verSz, rawLen, intTotalLen = 0; + word32 seqSz = 0, verSz = 0, rawLen, intTotalLen = 0; word32 sizes[DSA_INTS]; int i, j, outLen, ret = 0, mpSz; @@ -5059,17 +5082,14 @@ int wc_DsaKeyToDer(DsaKey* key, byte* output, word32 inLen) byte ver[MAX_VERSION_SZ]; byte* tmps[DSA_INTS]; - if (!key || !output) + if (ints > DSA_INTS) return BAD_FUNC_ARG; - if (key->type != DSA_PRIVATE) - return BAD_FUNC_ARG; - - for (i = 0; i < DSA_INTS; i++) + for (i = 0; i < ints; i++) tmps[i] = NULL; /* write all big ints from key to DER tmps */ - for (i = 0; i < DSA_INTS; i++) { + for (i = 0; i < ints; i++) { mp_int* keyInt = GetDsaInt(key, i); rawLen = mp_unsigned_bin_size(keyInt) + 1; @@ -5089,35 +5109,62 @@ int wc_DsaKeyToDer(DsaKey* key, byte* output, word32 inLen) } if (ret != 0) { - FreeTmpDsas(tmps, key->heap); + FreeTmpDsas(tmps, key->heap, ints); return ret; } /* make headers */ - verSz = SetMyVersion(0, ver, FALSE); + if (includeVersion) + verSz = SetMyVersion(0, ver, FALSE); seqSz = SetSequence(verSz + intTotalLen, seq); outLen = seqSz + verSz + intTotalLen; if (outLen > (int)inLen) { - FreeTmpDsas(tmps, key->heap); + FreeTmpDsas(tmps, key->heap, ints); return BAD_FUNC_ARG; } /* write to output */ XMEMCPY(output, seq, seqSz); j = seqSz; - XMEMCPY(output + j, ver, verSz); - j += verSz; + if (includeVersion) { + XMEMCPY(output + j, ver, verSz); + j += verSz; + } - for (i = 0; i < DSA_INTS; i++) { + for (i = 0; i < ints; i++) { XMEMCPY(output + j, tmps[i], sizes[i]); j += sizes[i]; } - FreeTmpDsas(tmps, key->heap); + FreeTmpDsas(tmps, key->heap, ints); return outLen; } +/* Convert private DsaKey key to DER format, write to output (inLen), + return bytes written */ +int wc_DsaKeyToDer(DsaKey* key, byte* output, word32 inLen) +{ + if (!key || !output) + return BAD_FUNC_ARG; + + if (key->type != DSA_PRIVATE) + return BAD_FUNC_ARG; + + return DsaKeyIntsToDer(key, output, inLen, DSA_INTS, 1); +} + +/* Convert DsaKey parameters to DER format, write to output (inLen), + return bytes written. Version is excluded to be compatible with + OpenSSL d2i_DSAparams */ +int wc_DsaKeyToParamsDer(DsaKey* key, byte* output, word32 inLen) +{ + if (!key || !output) + return BAD_FUNC_ARG; + + return DsaKeyIntsToDer(key, output, inLen, DSA_PARAM_INTS, 0); +} + #endif /* NO_DSA */ void InitDecodedCert(DecodedCert* cert, diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 446148a7a..e8e559890 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -196,6 +196,7 @@ extern const WOLFSSL_ObjectInfo wolfssl_object_info[]; #define WOLFSSL_TLS_FEATURE_SUM 92 #endif +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) /* NIDs */ enum { @@ -254,6 +255,7 @@ enum NID_X9_62_prime_field = 406 /* 1.2.840.10045.1.1 */ }; +#endif /* OPENSSL_EXTRA */ enum ECC_TYPES { @@ -305,6 +307,7 @@ enum Misc_ASN { KEYID_SIZE = WC_SHA_DIGEST_SIZE, #endif RSA_INTS = 8, /* RSA ints in private key */ + DSA_PARAM_INTS = 3, /* DSA paramater ints */ DSA_INTS = 5, /* DSA ints in private key */ MIN_DATE_SIZE = 12, MAX_DATE_SIZE = 32, @@ -330,7 +333,7 @@ enum Misc_ASN { MAX_ENCODED_DIG_ASN_SZ= 9, /* enum(bit or octet) + length(4) */ MAX_ENCODED_DIG_SZ = 64 + MAX_ENCODED_DIG_ASN_SZ, /* asn header + sha512 */ MAX_RSA_INT_SZ = 517, /* RSA raw sz 4096 for bits + tag + len(4) */ - MAX_DSA_INT_SZ = 261, /* DSA raw sz 2048 for bits + tag + len(4) */ + MAX_DSA_INT_SZ = 389, /* DSA raw sz 3072 for bits + tag + len(4) */ MAX_NTRU_KEY_SZ = 610, /* NTRU 112 bit public key */ MAX_NTRU_ENC_SZ = 628, /* NTRU 112 bit DER public encoding */ MAX_LENGTH_SZ = 4, /* Max length size for DER encoding */ diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index f55312c12..ed1775d91 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -32,6 +32,7 @@ This library defines the interface APIs for X509 certificates. #define WOLF_CRYPT_ASN_PUBLIC_H #include +#include #ifdef __cplusplus extern "C" { @@ -509,6 +510,13 @@ WOLFSSL_API void wc_FreeDer(DerBuffer** pDer); WOLFSSL_API int wc_RsaPublicKeyDerSize(RsaKey* key, int with_header); #endif +#ifndef NO_DSA + /* DSA parameter DER helper functions */ + WOLFSSL_API int wc_DsaParamsDecode(const byte* input, word32* inOutIdx, + DsaKey*, word32); + WOLFSSL_API int wc_DsaKeyToParamsDer(DsaKey* key, byte* output, word32 inLen); +#endif + #ifdef HAVE_ECC /* private key helpers */ WOLFSSL_API int wc_EccPrivateKeyDecode(const byte*, word32*,