Fixes for DH Pub key import/export and new test case. Improve wc_DhParamsToDer.

This commit is contained in:
David Garske 2021-05-24 13:59:01 -07:00
parent 6db0b42c7f
commit 9b215c5138
6 changed files with 113 additions and 96 deletions

Binary file not shown.

View File

@ -0,0 +1,14 @@
-----BEGIN PUBLIC KEY-----
MIICJDCCARcGCSqGSIb3DQEDATCCAQgCggEBAP//////////rfhUWKK7Spqv3FYg
Jz088di5xYPOLTaVqeE2QRRkM/vMk53OJJs++X0v42NjDHXY9oGyAq7EYXrT3x7V
1f1lYSQz9R9fBm7QhWNlVT3tGvO1VxNef1fJNZhPDHDg5ot34qaJ2vPv6HId8Vih
Nq3nNTCsyk9IOnl6vAqxgrMk+2HRCKlLssjj+7lq2rdg1/RoHU9Co945TfSuVu3n
Y3K7GQsHp8juCm1wngL84c334uzANATNKDQvYZFy/pzphYP/jk8SMu7ygYPD/jsb
TG+tczu1/LwuwiAFxY7xg30Wg7LG80omwbLv+ohrQjhhKFyX//////////8CAQID
ggEFAAKCAQBNP0zkbEZx/2ECcwtlT0bnLg+eQQRVQVGJqV6EvHoKNTQVvrHDHs3H
WheYX/+WPRub+swfHqcii5XuK9R04mPi/ZyqT75kaYMxXpBchV2ymeAFtfK2Gc0G
zaizWY2HhH+PCe69YW/FzbicpxWX0EQuLS4yIMU731BvjRe4hKNnJH6j7IwIeGwl
iALToGjOGiVGLptMgvTrs8kdFwySlFQPtd8/cUUzl02HGktACnG0Gb4zvc/zFWMG
N1yhncDnp4vToms/8ULINmsKQ4vp0IzNDzHNIuc5yI3rXZGLBm4fB9urK0+F+LtV
471wUVxzZl3RtvhEEODyCRxtAl38egiC
-----END PUBLIC KEY-----

View File

@ -10,3 +10,7 @@ openssl ec -inform pem -in certs/statickeys/ecc-secp256r1.pem -outform der -out
# Using one generated and capture with wolfSSL using wc_DhGenerateKeyPair (openssl generates DH keys with 2048-bits... based on the DH "p" prime size)
#openssl genpkey -paramfile certs/statickeys/dh-ffdhe2048-params.pem -out certs/statickeys/dh-ffdhe2048.der
openssl pkey -inform der -in certs/statickeys/dh-ffdhe2048.der -outform pem -out certs/statickeys/dh-ffdhe2048.pem
openssl pkey -inform der -in certs/statickeys/dh-ffdhe2048.der -outform der -out certs/statickeys/dh-ffdhe2048-pub.der -pubout
# Export DH public key as DER and convert to PEM
openssl pkey -inform der -in certs/statickeys/dh-ffdhe2048-pub.der -outform pem -out certs/statickeys/dh-ffdhe2048-pub.pem
openssl pkey -inform der -in certs/statickeys/dh-ffdhe2048-pub.der -outform pem -out certs/statickeys/dh-ffdhe2048-pub.pem -pubin

View File

@ -14,4 +14,6 @@ EXTRA_DIST += \
EXTRA_DIST += \
certs/statickeys/dh-ffdhe2048-params.pem \
certs/statickeys/dh-ffdhe2048.der \
certs/statickeys/dh-ffdhe2048.pem
certs/statickeys/dh-ffdhe2048.pem \
certs/statickeys/dh-ffdhe2048-pub.der \
certs/statickeys/dh-ffdhe2048-pub.pem

View File

@ -4731,11 +4731,10 @@ int wc_DhKeyDecode(const byte* input, word32* inOutIdx, DhKey* key, word32 inSz)
if (ret == ASN_DH_KEY_E) {
*inOutIdx = temp;
/* the version (0) */
if (GetASNInt(input, inOutIdx, &length, inSz) < 0) {
return ASN_PARSE_E;
/* the version (0) - private only (for public skip) */
if (GetASNInt(input, inOutIdx, &length, inSz) == 0) {
*inOutIdx += length;
}
*inOutIdx += length;
/* Size of dhKeyAgreement section */
if (GetSequence(input, inOutIdx, &length, inSz) < 0)
@ -4796,7 +4795,7 @@ int wc_DhKeyDecode(const byte* input, word32* inOutIdx, DhKey* key, word32 inSz)
/* Export DH Key (private or public) */
int wc_DhKeyToDer(DhKey* key, byte* output, word32* outSz, int exportPriv)
{
int privSz = 0, pubSz = 0, keySz;
int ret, privSz = 0, pubSz = 0, keySz;
word32 idx, total;
if (key == NULL || outSz == NULL) {
@ -4815,19 +4814,23 @@ int wc_DhKeyToDer(DhKey* key, byte* output, word32* outSz, int exportPriv)
idx = 1 + SetLength(pubSz, NULL) + pubSz; /* +1 for ASN_BIT_STRING */
}
keySz = idx;
/* integer - g */
idx += SetASNIntMP(&key->g, -1, NULL);
/* integer - p */
idx += SetASNIntMP(&key->p, -1, NULL);
/* sequence */
idx += SetSequence(idx, NULL);
/* DH Parameters sequence with P and G */
total = 0;
ret = wc_DhParamsToDer(key, NULL, &total);
if (ret != LENGTH_ONLY_E)
return ret;
idx += total;
/* object dhKeyAgreement 1.2.840.113549.1.3.1 */
idx += SetObjectId(sizeof(keyDhOid), NULL);
idx += sizeof(keyDhOid);
/* sequence */
idx += SetSequence(idx, NULL);
/* version: 0 (ASN_INTEGER, 0x01, 0x00) */
idx += 3;
if (exportPriv) {
/* version: 0 (ASN_INTEGER, 0x01, 0x00) */
idx += 3;
}
/* sequence */
total = idx + SetSequence(idx, NULL);
@ -4845,20 +4848,24 @@ int wc_DhKeyToDer(DhKey* key, byte* output, word32* outSz, int exportPriv)
/* sequence */
idx = SetSequence(total, output);
/* version: 0 */
idx += SetMyVersion(0, output + idx, 0);
if (exportPriv) {
/* version: 0 */
idx += SetMyVersion(0, output + idx, 0);
}
/* sequence - all but pub/priv */
idx += SetSequence(total - keySz - idx, output + idx);
/* object dhKeyAgreement 1.2.840.113549.1.3.1 */
idx += SetObjectId(sizeof(keyDhOid), output + idx);
XMEMCPY(output + idx, keyDhOid, sizeof(keyDhOid));
idx += sizeof(keyDhOid);
/* sequence */
idx += SetSequence(total - keySz - idx, output + idx);
/* integer - p */
idx += SetASNIntMP(&key->p, -1, output + idx);
/* integer - g */
idx += SetASNIntMP(&key->g, -1, output + idx);
/* DH Parameters sequence with P and G */
total = *outSz - idx;
ret = wc_DhParamsToDer(key, output + idx, &total);
if (ret < 0)
return ret;
idx += total;
/* octect string: priv */
if (exportPriv) {
idx += SetOctetString(privSz, output + idx);
@ -4892,77 +4899,42 @@ int wc_DhPrivKeyToDer(DhKey* key, byte* out, word32* outSz)
* version 2 build.
*
* return bytes written on success */
int wc_DhParamsToDer(DhKey* key, byte* out, word32* outSz)
int wc_DhParamsToDer(DhKey* key, byte* output, word32* outSz)
{
word32 sz = 0, idx = 0;
int pSz = 0, gSz = 0, ret;
byte scratch[MAX_LENGTH_SZ];
word32 idx, total;
if (key == NULL || outSz == NULL) {
return BAD_FUNC_ARG;
}
pSz = mp_unsigned_bin_size(&key->p);
if (pSz < 0) {
return pSz;
}
if (mp_leading_bit(&key->p)) {
pSz++;
}
/* determine size */
/* integer - g */
idx = SetASNIntMP(&key->g, -1, NULL);
/* integer - p */
idx += SetASNIntMP(&key->p, -1, NULL);
total = idx;
/* sequence */
idx += SetSequence(idx, NULL);
gSz = mp_unsigned_bin_size(&key->g);
if (gSz < 0) {
return gSz;
}
if (mp_leading_bit(&key->g)) {
gSz++;
}
sz = ASN_TAG_SZ; /* Integer */
sz += SetLength(pSz, scratch);
sz += ASN_TAG_SZ; /* Integer */
sz += SetLength(gSz, scratch);
sz += gSz + pSz;
if (out == NULL) {
byte seqScratch[MAX_SEQ_SZ];
*outSz = sz + SetSequence(sz, seqScratch);
if (output == NULL) {
*outSz = idx;
return LENGTH_ONLY_E;
}
if (*outSz < MAX_SEQ_SZ || *outSz < sz) {
/* make sure output fits in buffer */
if (idx > *outSz) {
return BUFFER_E;
}
idx += SetSequence(sz, out);
if (*outSz < idx + sz) {
return BUFFER_E;
}
out[idx++] = ASN_INTEGER;
idx += SetLength(pSz, out + idx);
if (mp_leading_bit(&key->p)) {
out[idx++] = 0x00;
pSz -= 1; /* subtract 1 from size to account for leading 0 */
}
ret = mp_to_unsigned_bin(&key->p, out + idx);
if (ret != MP_OKAY) {
return BUFFER_E;
}
idx += pSz;
/* write DH parameters */
/* sequence - for P and G only */
idx = SetSequence(total, output);
/* integer - p */
idx += SetASNIntMP(&key->p, -1, output + idx);
/* integer - g */
idx += SetASNIntMP(&key->g, -1, output + idx);
*outSz = idx;
out[idx++] = ASN_INTEGER;
idx += SetLength(gSz, out + idx);
if (mp_leading_bit(&key->g)) {
out[idx++] = 0x00;
gSz -= 1; /* subtract 1 from size to account for leading 0 */
}
ret = mp_to_unsigned_bin(&key->g, out + idx);
if (ret != MP_OKAY) {
return BUFFER_E;
}
idx += gSz;
return idx;
}

View File

@ -11997,6 +11997,7 @@ byte GetEntropy(ENTROPY_CMD cmd, byte* out)
#if defined(WOLFSSL_DH_EXTRA) && (!defined(HAVE_FIPS) || \
(defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2)))
static const char* dhKeyFile = CERT_ROOT "statickeys/dh-ffdhe2048.der";
static const char* dhKeyPubFile = CERT_ROOT "statickeys/dh-ffdhe2048-pub.der";
#endif
#endif
#ifndef NO_DSA
@ -16657,8 +16658,9 @@ WOLFSSL_TEST_SUBROUTINE int dh_test(void)
ERROR_OUT(-8120, done);
}
#if !defined(NO_ASN) && !defined(NO_FILESYSTEM)
#ifndef NO_ASN
{
/* DH Private - Key Export / Import */
#ifdef WOLFSSL_SMALL_STACK
byte *tmp2;
#else
@ -16666,19 +16668,19 @@ WOLFSSL_TEST_SUBROUTINE int dh_test(void)
#endif
XFILE file = XFOPEN(dhKeyFile, "rb");
if (!file)
ERROR_OUT(-8121, done);
ERROR_OUT(-8130, done);
bytes = (word32)XFREAD(tmp, 1, DH_TEST_TMP_SIZE, file);
XFCLOSE(file);
#ifdef WOLFSSL_SMALL_STACK
tmp2 = (byte*)XMALLOC(DH_TEST_TMP_SIZE, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
if (tmp2 == NULL)
ERROR_OUT(-8122, done);
ERROR_OUT(-8131, done);
#endif
idx = 0;
XMEMSET(tmp2, 0, DH_TEST_TMP_SIZE);
/* Import DH key as DER */
/* Import DH Private key as DER */
ret = wc_DhKeyDecode(tmp, &idx, key, bytes);
if (ret == 0) {
/* Export as DER */
@ -16688,7 +16690,31 @@ WOLFSSL_TEST_SUBROUTINE int dh_test(void)
/* Verify export matches original */
if (ret <= 0 || bytes != idx || XMEMCMP(tmp, tmp2, bytes) != 0) {
ERROR_OUT(-8123, done);
ERROR_OUT(-8132, done);
}
/* DH Public Key - Export / Import */
file = XFOPEN(dhKeyPubFile, "rb");
if (!file)
ERROR_OUT(-8133, done);
bytes = (word32)XFREAD(tmp, 1, DH_TEST_TMP_SIZE, file);
XFCLOSE(file);
idx = 0;
XMEMSET(tmp2, 0, DH_TEST_TMP_SIZE);
/* Import DH Public key as DER */
ret = wc_DhKeyDecode(tmp, &idx, key, bytes);
if (ret == 0) {
/* Export as DER */
idx = DH_TEST_TMP_SIZE;
ret = wc_DhPubKeyToDer(key, tmp2, &idx);
}
/* Verify export matches original */
if (ret <= 0 || bytes != idx || XMEMCMP(tmp, tmp2, bytes) != 0) {
ERROR_OUT(-8134, done);
}
#ifdef WOLFSSL_SMALL_STACK
@ -16698,37 +16724,36 @@ WOLFSSL_TEST_SUBROUTINE int dh_test(void)
#else
ret = wc_DhSetKey(key, dh_p, sizeof(dh_p), dh_g, sizeof(dh_g));
if (ret != 0) {
ERROR_OUT(-8123, done);
ERROR_OUT(-8121, done);
}
#endif
#endif /* !NO_ASN */
privSz = DH_TEST_BUF_SIZE;
pubSz = DH_TEST_BUF_SIZE;
ret = wc_DhExportKeyPair(key, priv, &privSz, pub, &pubSz);
if (ret != 0) {
ERROR_OUT(-8124, done);
ERROR_OUT(-8122, done);
}
ret = wc_DhImportKeyPair(key2, priv, privSz, pub, pubSz);
if (ret != 0) {
ERROR_OUT(-8125, done);
}
#endif /* WOLFSSL_DH_EXTRA */
#endif /* WOLFSSL_DH_EXTRA && !NO_FILESYSTEM && !FIPS <= 2 */
#ifndef WC_NO_RNG
ret = dh_generate_test(&rng);
if (ret != 0)
ERROR_OUT(-8126, done);
ERROR_OUT(-8123, done);
ret = dh_fips_generate_test(&rng);
if (ret != 0)
ERROR_OUT(-8127, done);
ERROR_OUT(-8124, done);
#endif /* !WC_NO_RNG */
#if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)
ret = dh_test_check_pubvalue();
if (ret != 0)
ERROR_OUT(-8128, done);
ERROR_OUT(-8125, done);
#endif
#ifndef WC_NO_RNG
@ -16736,17 +16761,17 @@ WOLFSSL_TEST_SUBROUTINE int dh_test(void)
#ifdef HAVE_FFDHE_2048
ret = dh_ffdhe_test(&rng, wc_Dh_ffdhe2048_Get());
if (ret != 0)
ERROR_OUT(-8129, done);
ERROR_OUT(-8126, done);
#endif
#ifdef HAVE_FFDHE_3072
ret = dh_ffdhe_test(&rng, wc_Dh_ffdhe3072_Get());
if (ret != 0)
ERROR_OUT(-8130, done);
ERROR_OUT(-8127, done);
#endif
#ifdef HAVE_FFDHE_4096
ret = dh_ffdhe_test(&rng, wc_Dh_ffdhe4096_Get());
if (ret != 0)
ERROR_OUT(-8131, done);
ERROR_OUT(-8128, done);
#endif
#endif /* !WC_NO_RNG */
@ -16759,7 +16784,7 @@ WOLFSSL_TEST_SUBROUTINE int dh_test(void)
ret = wc_DhSetCheckKey(key, dh_p, sizeof(dh_p), dh_g, sizeof(dh_g),
NULL, 0, 0, &rng);
if (ret != 0)
ERROR_OUT(-8132, done);
ERROR_OUT(-8129, done);
keyInit = 1; /* DhSetCheckKey also initializes the key, free it */
#endif