From 34d240a491d0a5ccf2b9bf0f6cda8109d05f72ce Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Tue, 4 Apr 2017 00:32:22 -0400 Subject: Rework PKCS #8 PrivateKeyInfo wrapper code. Handle AlgorithmIdentifier.parameters as in SubjectPublicKeyInfo: the field is OPTIONAL, but it's usually set to NULL if no OID is present. I have a vague memory that this is fallout from a specification error years ago in which the OPTIONAL was accidently left out. Whatever. --- asn1.c | 54 +++++++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/asn1.c b/asn1.c index 100dc3c..1d7e628 100644 --- a/asn1.c +++ b/asn1.c @@ -188,12 +188,14 @@ hal_error_t hal_asn1_encode_spki(const uint8_t * const alg_oid, const size_t a (err = hal_asn1_encode_header(ASN1_BIT_STRING, 1 + pubkey_len, NULL, &hlen_bit, 0)) != HAL_OK) return err; - const size_t algid_len = hlen_alg + alg_oid_len + hlen_curve + curve_oid_len; + const size_t algid_len = + hlen_alg + alg_oid_len + hlen_curve + curve_oid_len; if ((err = hal_asn1_encode_header(ASN1_SEQUENCE, algid_len, NULL, &hlen_algid, 0)) != HAL_OK) return err; - const size_t vlen = hlen_algid + hlen_alg + alg_oid_len + hlen_curve + curve_oid_len + hlen_bit + 1 + pubkey_len; + const size_t vlen = + hlen_algid + hlen_alg + alg_oid_len + hlen_curve + curve_oid_len + hlen_bit + 1 + pubkey_len; if ((err = hal_asn1_encode_header(ASN1_SEQUENCE, vlen, NULL, &hlen_spki, 0)) != HAL_OK) return err; @@ -236,7 +238,6 @@ hal_error_t hal_asn1_encode_spki(const uint8_t * const alg_oid, const size_t a return err; d += hlen; *d++ = 0x00; - d += pubkey_len; /* pubkey handled early, above. */ assert(d == der + hlen_spki + vlen); @@ -258,47 +259,52 @@ hal_error_t hal_asn1_encode_pkcs8_privatekeyinfo(const uint8_t * const alg_oid, (der != NULL && privkey == NULL) || (curve_oid == NULL && curve_oid_len != 0)) return HAL_ERROR_BAD_ARGUMENTS; + const uint8_t curve_oid_tag = curve_oid == NULL ? ASN1_NULL : ASN1_OBJECT_IDENTIFIER; + fp_int version[1] = INIT_FP_INT; hal_error_t err; - size_t version_len, hlen, hlen_pkcs8, hlen_algid, hlen_alg, hlen_curve = 0, hlen_oct; + size_t version_len, hlen, hlen_algid, hlen_alg, hlen_curve, hlen_oct; if ((err = hal_asn1_encode_integer(version, NULL, &version_len, 0)) != HAL_OK || (err = hal_asn1_encode_header(ASN1_OBJECT_IDENTIFIER, alg_oid_len, NULL, &hlen_alg, 0)) != HAL_OK || + (err = hal_asn1_encode_header(curve_oid_tag, curve_oid_len, NULL, &hlen_curve, 0)) != HAL_OK || (err = hal_asn1_encode_header(ASN1_OCTET_STRING, privkey_len, NULL, &hlen_oct, 0)) != HAL_OK) return err; - if (curve_oid != NULL && - (err = hal_asn1_encode_header(ASN1_OBJECT_IDENTIFIER, curve_oid_len, NULL, &hlen_curve, 0)) != HAL_OK) - return err; - - const size_t algid_len = hlen_alg + alg_oid_len + hlen_curve + curve_oid_len; + const size_t algid_len = + hlen_alg + alg_oid_len + hlen_curve + curve_oid_len; if ((err = hal_asn1_encode_header(ASN1_SEQUENCE, algid_len, NULL, &hlen_algid, 0)) != HAL_OK) return err; - const size_t vlen = version_len + hlen_algid + hlen_alg + alg_oid_len + hlen_curve + curve_oid_len + hlen_oct + privkey_len; + const size_t vlen = + version_len + hlen_algid + hlen_alg + alg_oid_len + hlen_curve + curve_oid_len + hlen_oct + privkey_len; - if ((err = hal_asn1_encode_header(ASN1_SEQUENCE, vlen, NULL, &hlen_pkcs8, 0)) != HAL_OK) + if ((err = hal_asn1_encode_header(ASN1_SEQUENCE, vlen, NULL, &hlen, 0)) != HAL_OK) return err; + if (der_len != NULL) + *der_len = hlen + vlen; + + if (der == NULL) + return HAL_OK; + + uint8_t * const der_end = der + hlen + vlen; + /* * Handle privkey early, in case it was staged into our output buffer. */ - if (der != NULL && hlen_pkcs8 + vlen <= der_max) - memmove(der + hlen_pkcs8 + vlen - privkey_len, privkey, privkey_len); - - err = hal_asn1_encode_header(ASN1_SEQUENCE, vlen, der, &hlen, der_max); + if (der_end <= der + der_max) + memmove(der_end - privkey_len, privkey, privkey_len); - if (der_len != NULL) - *der_len = hlen + vlen; + uint8_t *d = der; + memset(d, 0, hlen + vlen - privkey_len); - if (der == NULL || err != HAL_OK) + if ((err = hal_asn1_encode_header(ASN1_SEQUENCE, vlen, d, &hlen, der + der_max - d)) != HAL_OK) return err; - - uint8_t *d = der + hlen; - memset(d, 0, vlen - privkey_len); + d += hlen; if ((err = hal_asn1_encode_integer(version, d, NULL, der + der_max - d)) != HAL_OK) return err; @@ -314,8 +320,7 @@ hal_error_t hal_asn1_encode_pkcs8_privatekeyinfo(const uint8_t * const alg_oid, memcpy(d, alg_oid, alg_oid_len); d += alg_oid_len; - if (curve_oid != NULL && - (err = hal_asn1_encode_header(ASN1_OBJECT_IDENTIFIER, curve_oid_len, d, &hlen, der + der_max - d)) != HAL_OK) + if ((err = hal_asn1_encode_header(curve_oid_tag, curve_oid_len, d, &hlen, der + der_max - d)) != HAL_OK) return err; d += hlen; if (curve_oid != NULL) @@ -325,10 +330,9 @@ hal_error_t hal_asn1_encode_pkcs8_privatekeyinfo(const uint8_t * const alg_oid, if ((err = hal_asn1_encode_header(ASN1_OCTET_STRING, privkey_len, d, &hlen, der + der_max - d)) != HAL_OK) return err; d += hlen; - d += privkey_len; /* privkey handled early, above. */ - assert(d == der + hlen_pkcs8 + vlen); + assert(d == der_end); assert(d <= der + der_max); return HAL_OK; -- cgit v1.2.3