diff options
-rw-r--r-- | asn1.c | 336 | ||||
-rw-r--r-- | asn1_internal.h | 32 | ||||
-rw-r--r-- | ecdsa.c | 168 | ||||
-rw-r--r-- | pkcs8.py | 324 | ||||
-rw-r--r-- | rsa.c | 54 | ||||
-rw-r--r-- | unit-tests.py | 261 |
6 files changed, 939 insertions, 236 deletions
@@ -55,6 +55,18 @@ #include "asn1_internal.h" +#define INIT_FP_INT {{{0}}} + +/* + * Algorithm OIDs used in SPKI and PKCS #8. + */ + +const uint8_t hal_asn1_oid_rsaEncryption[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01 }; +const size_t hal_asn1_oid_rsaEncryption_len = sizeof(hal_asn1_oid_rsaEncryption); + +const uint8_t hal_asn1_oid_ecPublicKey[] = { 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01 }; +const size_t hal_asn1_oid_ecPublicKey_len = sizeof(hal_asn1_oid_ecPublicKey); + /* * Encode tag and length fields of an ASN.1 object. * @@ -153,7 +165,7 @@ hal_error_t hal_asn1_encode_integer(const fp_int * const bn, } /* - * Encode a public key into an RFC 5280 SubjectPublicKeyInfo. + * Encode a public key into a X.509 SubjectPublicKeyInfo (RFC 5280). */ hal_error_t hal_asn1_encode_spki(const uint8_t * const alg_oid, const size_t alg_oid_len, @@ -234,6 +246,164 @@ hal_error_t hal_asn1_encode_spki(const uint8_t * const alg_oid, const size_t a } /* + * Encode a PKCS #8 PrivateKeyInfo (RFC 5208). + */ + +hal_error_t hal_asn1_encode_pkcs8_privatekeyinfo(const uint8_t * const alg_oid, const size_t alg_oid_len, + const uint8_t * const curve_oid, const size_t curve_oid_len, + const uint8_t * const privkey, const size_t privkey_len, + uint8_t *der, size_t *der_len, const size_t der_max) +{ + if (alg_oid == NULL || alg_oid_len == 0 || privkey_len == 0 || + (der != NULL && privkey == NULL) || (curve_oid == NULL && curve_oid_len != 0)) + return HAL_ERROR_BAD_ARGUMENTS; + + 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; + + 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(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; + + 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; + + if ((err = hal_asn1_encode_header(ASN1_SEQUENCE, vlen, NULL, &hlen_pkcs8, 0)) != HAL_OK) + return err; + + /* + * 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_len != NULL) + *der_len = hlen + vlen; + + if (der == NULL || err != HAL_OK) + return err; + + uint8_t *d = der + hlen; + memset(d, 0, vlen - privkey_len); + + if ((err = hal_asn1_encode_integer(version, d, NULL, der + der_max - d)) != HAL_OK) + return err; + d += version_len; + + if ((err = hal_asn1_encode_header(ASN1_SEQUENCE, algid_len, d, &hlen, der + der_max - d)) != HAL_OK) + return err; + d += hlen; + + if ((err = hal_asn1_encode_header(ASN1_OBJECT_IDENTIFIER, alg_oid_len, d, &hlen, der + der_max - d)) != HAL_OK) + return err; + d += hlen; + 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) + return err; + d += hlen; + if (curve_oid != NULL) + memcpy(d, curve_oid, curve_oid_len); + d += curve_oid_len; + + 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 + der_max); + + return HAL_OK; +} + +/* + * Encode a PKCS #8 EncryptedPrivateKeyInfo (RFC 5208). + */ + +hal_error_t hal_asn1_encode_pkcs8_encryptedprivatekeyinfo(const uint8_t * const alg_oid, const size_t alg_oid_len, + const uint8_t * const data, const size_t data_len, + uint8_t *der, size_t *der_len, const size_t der_max) +{ + if (alg_oid == NULL || alg_oid_len == 0 || data_len == 0 || (der != NULL && data == NULL)) + return HAL_ERROR_BAD_ARGUMENTS; + + hal_error_t err; + + size_t hlen, hlen_pkcs8, hlen_algid, hlen_alg, hlen_oct; + + if ((err = hal_asn1_encode_header(ASN1_OBJECT_IDENTIFIER, alg_oid_len, NULL, &hlen_alg, 0)) != HAL_OK || + (err = hal_asn1_encode_header(ASN1_OCTET_STRING, data_len, NULL, &hlen_oct, 0)) != HAL_OK) + return err; + + const size_t algid_len = hlen_alg + alg_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_oct + data_len; + + if ((err = hal_asn1_encode_header(ASN1_SEQUENCE, vlen, NULL, &hlen_pkcs8, 0)) != HAL_OK) + return err; + + /* + * Handle data early, in case it was staged into our output buffer. + */ + if (der != NULL && hlen_pkcs8 + vlen <= der_max) + memmove(der + hlen_pkcs8 + vlen - data_len, data, data_len); + + err = hal_asn1_encode_header(ASN1_SEQUENCE, vlen, der, &hlen, der_max); + + if (der_len != NULL) + *der_len = hlen + vlen; + + if (der == NULL || err != HAL_OK) + return err; + + uint8_t *d = der + hlen; + memset(d, 0, vlen - data_len); + + if ((err = hal_asn1_encode_header(ASN1_SEQUENCE, algid_len, d, &hlen, der + der_max - d)) != HAL_OK) + return err; + d += hlen; + + if ((err = hal_asn1_encode_header(ASN1_OBJECT_IDENTIFIER, alg_oid_len, d, &hlen, der + der_max - d)) != HAL_OK) + return err; + d += hlen; + memcpy(d, alg_oid, alg_oid_len); + d += alg_oid_len; + + if ((err = hal_asn1_encode_header(ASN1_OCTET_STRING, data_len, d, &hlen, der + der_max - d)) != HAL_OK) + return err; + d += hlen; + + d += data_len; /* data handled early, above. */ + + assert(d == der + hlen_pkcs8 + vlen); + assert(d <= der + der_max); + + return HAL_OK; +} + + +/* * Parse tag and length of an ASN.1 object. Tag must match value * specified by the caller. On success, sets hlen and vlen to lengths * of header and value, respectively. @@ -300,7 +470,7 @@ hal_error_t hal_asn1_decode_integer(fp_int *bn, } /* - * Decode a public key from an RFC 5280 SubjectPublicKeyInfo. + * Decode a public key from a X.509 SubjectPublicKeyInfo (RFC 5280). */ hal_error_t hal_asn1_decode_spki(const uint8_t **alg_oid, size_t *alg_oid_len, @@ -322,6 +492,9 @@ hal_error_t hal_asn1_decode_spki(const uint8_t **alg_oid, size_t *alg_oid_len, return err; d += hlen; + if (hlen + vlen != der_len) + return HAL_ERROR_ASN1_PARSE_FAILED; + if ((err = hal_asn1_decode_header(ASN1_SEQUENCE, d, der_end - d, &hlen, &vlen)) != HAL_OK) return err; d += hlen; @@ -385,6 +558,165 @@ hal_error_t hal_asn1_decode_spki(const uint8_t **alg_oid, size_t *alg_oid_len, } /* + * Decode a private key from a PKCS #8 PrivateKeyInfo (RFC 5208). + */ + +hal_error_t hal_asn1_decode_pkcs8_privatekeyinfo(const uint8_t **alg_oid, size_t *alg_oid_len, + const uint8_t **curve_oid, size_t *curve_oid_len, + const uint8_t **privkey, size_t *privkey_len, + const uint8_t *const der, const size_t der_len) +{ + if (der == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + const uint8_t * const der_end = der + der_len; + const uint8_t *d = der; + + fp_int version[1] = INIT_FP_INT; + size_t hlen, vlen; + hal_error_t err; + + if ((err = hal_asn1_decode_header(ASN1_SEQUENCE, d, der_end - d, &hlen, &vlen)) != HAL_OK) + return err; + d += hlen; + + if (hlen + vlen != der_len) + return HAL_ERROR_ASN1_PARSE_FAILED; + + if ((err - hal_asn1_decode_integer(version, d, &hlen, der_end - d)) != HAL_OK) + return err; + if (!fp_iszero(version)) + return HAL_ERROR_ASN1_PARSE_FAILED; + d += hlen; + + if ((err = hal_asn1_decode_header(ASN1_SEQUENCE, d, der_end - d, &hlen, &vlen)) != HAL_OK) + return err; + d += hlen; + + const uint8_t * const algid_end = d + vlen; + + if ((err = hal_asn1_decode_header(ASN1_OBJECT_IDENTIFIER, d, algid_end - d, &hlen, &vlen)) != HAL_OK) + return err; + d += hlen; + if (vlen > algid_end - d) + return HAL_ERROR_ASN1_PARSE_FAILED; + if (alg_oid != NULL) + *alg_oid = d; + if (alg_oid_len != NULL) + *alg_oid_len = vlen; + d += vlen; + + if (curve_oid != NULL) + *curve_oid = NULL; + if (curve_oid_len != NULL) + *curve_oid_len = 0; + + if (d < algid_end) { + switch (*d) { + + case ASN1_OBJECT_IDENTIFIER: + if ((err = hal_asn1_decode_header(ASN1_OBJECT_IDENTIFIER, d, algid_end - d, &hlen, &vlen)) != HAL_OK) + return err; + d += hlen; + if (vlen > algid_end - d) + return HAL_ERROR_ASN1_PARSE_FAILED; + if (curve_oid != NULL) + *curve_oid = d; + if (curve_oid_len != NULL) + *curve_oid_len = vlen; + d += vlen; + break; + + case ASN1_NULL: + if ((err = hal_asn1_decode_header(ASN1_NULL, d, algid_end - d, &hlen, &vlen)) != HAL_OK) + return err; + d += hlen; + if (vlen == 0) + break; + + default: + return HAL_ERROR_ASN1_PARSE_FAILED; + } + } + + if (d != algid_end) + return HAL_ERROR_ASN1_PARSE_FAILED; + + if ((err = hal_asn1_decode_header(ASN1_OCTET_STRING, d, der_end - d, &hlen, &vlen)) != HAL_OK) + return err; + d += hlen; + if (vlen >= algid_end - d) + return HAL_ERROR_ASN1_PARSE_FAILED; + if (privkey != NULL) + *privkey = d; + if (privkey_len != NULL) + *privkey_len = vlen; + d += vlen; + + if (d != der_end) + return HAL_ERROR_ASN1_PARSE_FAILED; + + return HAL_OK; +} + +/* + * Decode a private key from a PKCS #8 EncryptedPrivateKeyInfo (RFC 5208). + */ + +hal_error_t hal_asn1_decode_pkcs8_encryptedprivatekeyinfo(const uint8_t **alg_oid, size_t *alg_oid_len, + const uint8_t **data, size_t *data_len, + const uint8_t *const der, const size_t der_len) +{ + if (alg_oid == NULL || alg_oid_len == NULL || data == NULL || data_len == NULL || der == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + const uint8_t * const der_end = der + der_len; + const uint8_t *d = der; + + size_t hlen, vlen; + hal_error_t err; + + if ((err = hal_asn1_decode_header(ASN1_SEQUENCE, d, der_end - d, &hlen, &vlen)) != HAL_OK) + return err; + d += hlen; + + if (hlen + vlen != der_len) + return HAL_ERROR_ASN1_PARSE_FAILED; + + if ((err = hal_asn1_decode_header(ASN1_SEQUENCE, d, der_end - d, &hlen, &vlen)) != HAL_OK) + return err; + d += hlen; + + const uint8_t * const algid_end = d + vlen; + + if ((err = hal_asn1_decode_header(ASN1_OBJECT_IDENTIFIER, d, algid_end - d, &hlen, &vlen)) != HAL_OK) + return err; + d += hlen; + if (vlen > algid_end - d) + return HAL_ERROR_ASN1_PARSE_FAILED; + *alg_oid = d; + *alg_oid_len = vlen; + d += vlen; + + if (d != algid_end) + return HAL_ERROR_ASN1_PARSE_FAILED; + + if ((err = hal_asn1_decode_header(ASN1_OCTET_STRING, d, der_end - d, &hlen, &vlen)) != HAL_OK) + return err; + d += hlen; + if (vlen >= algid_end - d) + return HAL_ERROR_ASN1_PARSE_FAILED; + *data = d; + *data_len = vlen; + d += vlen; + + if (d != der_end) + return HAL_ERROR_ASN1_PARSE_FAILED; + + return HAL_OK; +} + +/* * Local variables: * indent-tabs-mode: nil * End: diff --git a/asn1_internal.h b/asn1_internal.h index 0b08b84..c337d4b 100644 --- a/asn1_internal.h +++ b/asn1_internal.h @@ -89,6 +89,20 @@ static inline uint8_t *unconst_uint8_t(const uint8_t * const arg) return (uint8_t *) arg; } +/* + * OIDs. + */ + +extern const uint8_t hal_asn1_oid_rsaEncryption[]; +extern const size_t hal_asn1_oid_rsaEncryption_len; + +extern const uint8_t hal_asn1_oid_ecPublicKey[]; +extern const size_t hal_asn1_oid_ecPublicKey_len; + +/* + * Transcoding functions. + */ + extern hal_error_t hal_asn1_encode_header(const uint8_t tag, const size_t value_len, uint8_t *der, size_t *der_len, const size_t der_max); @@ -113,6 +127,24 @@ extern hal_error_t hal_asn1_decode_spki(const uint8_t **alg_oid, size_t *alg_o const uint8_t **pubkey, size_t *pubkey_len, const uint8_t *const der, const size_t der_len); +extern hal_error_t hal_asn1_encode_pkcs8_privatekeyinfo(const uint8_t * const alg_oid, const size_t alg_oid_len, + const uint8_t * const curve_oid, const size_t curve_oid_len, + const uint8_t * const privkey, const size_t privkey_len, + uint8_t *der, size_t *der_len, const size_t der_max); + +extern hal_error_t hal_asn1_decode_pkcs8_privatekeyinfo(const uint8_t **alg_oid, size_t *alg_oid_len, + const uint8_t **curve_oid, size_t *curve_oid_len, + const uint8_t **privkey, size_t *privkey_len, + const uint8_t *const der, const size_t der_len); + +extern hal_error_t hal_asn1_encode_pkcs8_encryptedprivatekeyinfo(const uint8_t * const alg_oid, const size_t alg_oid_len, + const uint8_t * const data, const size_t data_len, + uint8_t *der, size_t *der_len, const size_t der_max); + +extern hal_error_t hal_asn1_decode_pkcs8_encryptedprivatekeyinfo(const uint8_t **alg_oid, size_t *alg_oid_len, + const uint8_t **data, size_t *data_len, + const uint8_t *const der, const size_t der_len); + #endif /* _HAL_ASN1_INTERNAL_H_ */ /* @@ -833,44 +833,6 @@ static hal_error_t verilog_point_pick_random(const verilog_ecdsa_driver_t * cons #endif -static inline hal_error_t verilog_p256_point_pick_random(fp_int *k, ec_point_t *P) -{ -#if HAL_ECDSA_VERILOG_ECDSA256_MULTIPLIER - - static const verilog_ecdsa_driver_t p256_driver = { - .name = ECDSA256_NAME, - .bytes = ECDSA256_OPERAND_BITS / 8, - .k_addr = ECDSA256_ADDR_K, - .x_addr = ECDSA256_ADDR_X, - .y_addr = ECDSA256_ADDR_Y - }; - - return verilog_point_pick_random(&p256_driver, k, P); - -#endif - - return HAL_ERROR_CORE_NOT_FOUND; -} - -static inline hal_error_t verilog_p384_point_pick_random(fp_int *k, ec_point_t *P) -{ -#if HAL_ECDSA_VERILOG_ECDSA384_MULTIPLIER - - static const verilog_ecdsa_driver_t p384_driver = { - .name = ECDSA384_NAME, - .bytes = ECDSA384_OPERAND_BITS / 8, - .k_addr = ECDSA384_ADDR_K, - .x_addr = ECDSA384_ADDR_X, - .y_addr = ECDSA384_ADDR_Y - }; - - return verilog_point_pick_random(&p384_driver, k, P); - -#endif - - return HAL_ERROR_CORE_NOT_FOUND; -} - /* * Pick a random point on the curve, return random scalar and * resulting point. @@ -915,23 +877,39 @@ static hal_error_t point_pick_random(const ecdsa_curve_t * const curve, memset(k_buf, 0, sizeof(k_buf)); -#if HAL_ECDSA_VERILOG_ECDSA256_MULTIPLIER || HAL_ECDSA_VERILOG_ECDSA384_MULTIPLIER switch (curve->curve) { - case HAL_CURVE_P256: - if ((err = verilog_p256_point_pick_random(k, P)) != HAL_ERROR_CORE_NOT_FOUND) +#if HAL_ECDSA_VERILOG_ECDSA256_MULTIPLIER + case HAL_CURVE_P256:; + static const verilog_ecdsa_driver_t p256_driver = { + .name = ECDSA256_NAME, + .bytes = ECDSA256_OPERAND_BITS / 8, + .k_addr = ECDSA256_ADDR_K, + .x_addr = ECDSA256_ADDR_X, + .y_addr = ECDSA256_ADDR_Y + }; + if ((err = verilog_point_pick_random(&p256_driver, k, P)) != HAL_ERROR_CORE_NOT_FOUND) return err; - break; + break; +#endif - case HAL_CURVE_P384: - if ((err = verilog_p384_point_pick_random(k, P)) != HAL_ERROR_CORE_NOT_FOUND) +#if HAL_ECDSA_VERILOG_ECDSA384_MULTIPLIER + case HAL_CURVE_P384:; + static const verilog_ecdsa_driver_t p384_driver = { + .name = ECDSA384_NAME, + .bytes = ECDSA384_OPERAND_BITS / 8, + .k_addr = ECDSA384_ADDR_K, + .x_addr = ECDSA384_ADDR_X, + .y_addr = ECDSA384_ADDR_Y + }; + if ((err = verilog_point_pick_random(&p384_driver, k, P)) != HAL_ERROR_CORE_NOT_FOUND) return err; - break; + break; +#endif default: break; } -#endif /* * Calculate P = kG and return. @@ -1287,7 +1265,11 @@ hal_error_t hal_ecdsa_key_from_ecpoint(hal_ecdsa_key_t **key_, } /* - * Write private key in RFC 5915 ASN.1 DER format. + * Write private key in PKCS #8 PrivateKeyInfo DER format (RFC 5208). + * This is basically just the PKCS #8 wrapper around the ECPrivateKey + * format from RFC 5915, except that the OID naming the curve is in + * the privateKeyAlgorithm.parameters field in the PKCS #8 wrapper and + * is therefore omitted from the ECPrivateKey. * * This is hand-coded, and is approaching the limit where one should * probably be using an ASN.1 compiler like asn1c instead. @@ -1314,27 +1296,29 @@ hal_error_t hal_ecdsa_private_key_to_der(const hal_ecdsa_key_t * const key, hal_error_t err; - size_t version_len, hlen, hlen_oct, hlen_oid, hlen_exp0, hlen_bit, hlen_exp1; + size_t version_len, hlen, hlen_oct, hlen_bit, hlen_exp1; if ((err = hal_asn1_encode_integer(version, NULL, &version_len, 0)) != HAL_OK || (err = hal_asn1_encode_header(ASN1_OCTET_STRING, q_len, NULL, &hlen_oct, 0)) != HAL_OK || - (err = hal_asn1_encode_header(ASN1_OBJECT_IDENTIFIER, curve->oid_len, NULL, &hlen_oid, 0)) != HAL_OK || - (err = hal_asn1_encode_header(ASN1_EXPLICIT_0, hlen_oid + curve->oid_len, NULL, &hlen_exp0, 0)) != HAL_OK || (err = hal_asn1_encode_header(ASN1_BIT_STRING, (q_len + 1) * 2, NULL, &hlen_bit, 0)) != HAL_OK || (err = hal_asn1_encode_header(ASN1_EXPLICIT_1, hlen_bit + (q_len + 1) * 2, NULL, &hlen_exp1, 0)) != HAL_OK) return err; - const size_t vlen = (version_len + - hlen_oct + q_len + - hlen_oid + hlen_exp0 + curve->oid_len + - hlen_bit + hlen_exp1 + (q_len + 1) * 2); + const size_t vlen = version_len + hlen_oct + q_len + hlen_exp1 + hlen_bit + (q_len + 1) * 2; - err = hal_asn1_encode_header(ASN1_SEQUENCE, vlen, der, &hlen, der_max); + 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 ((err = hal_asn1_encode_pkcs8_privatekeyinfo(hal_asn1_oid_ecPublicKey, hal_asn1_oid_ecPublicKey_len, + curve->oid, curve->oid_len, + NULL, hlen + vlen, + NULL, der_len, der_max)) != HAL_OK) + return err; + + if (der == NULL) + return HAL_OK; - if (der == NULL || err != HAL_OK) + if ((err = hal_asn1_encode_header(ASN1_SEQUENCE, vlen, der, &hlen, der_max)) != HAL_OK) return err; uint8_t *d = der + hlen; @@ -1350,15 +1334,6 @@ hal_error_t hal_ecdsa_private_key_to_der(const hal_ecdsa_key_t * const key, fp_to_unsigned_bin(unconst_fp_int(key->d), d + q_len - d_len); d += q_len; - if ((err = hal_asn1_encode_header(ASN1_EXPLICIT_0, hlen_oid + curve->oid_len, d, &hlen, der + der_max - d)) != HAL_OK) - return err; - d += hlen; - if ((err = hal_asn1_encode_header(ASN1_OBJECT_IDENTIFIER, curve->oid_len, d, &hlen, der + der_max - d)) != HAL_OK) - return err; - d += hlen; - memcpy(d, curve->oid, curve->oid_len); - d += curve->oid_len; - if ((err = hal_asn1_encode_header(ASN1_EXPLICIT_1, hlen_bit + (q_len + 1) * 2, d, &hlen, der + der_max - d)) != HAL_OK) return err; d += hlen; @@ -1372,9 +1347,10 @@ hal_error_t hal_ecdsa_private_key_to_der(const hal_ecdsa_key_t * const key, fp_to_unsigned_bin(unconst_fp_int(key->Q->y), d + q_len - Qy_len); d += q_len; - assert(d <= der + der_max); - - return HAL_OK; + return hal_asn1_encode_pkcs8_privatekeyinfo(hal_asn1_oid_ecPublicKey, hal_asn1_oid_ecPublicKey_len, + curve->oid, curve->oid_len, + der, d - der, + der, der_len, der_max); } /* @@ -1389,7 +1365,7 @@ size_t hal_ecdsa_private_key_to_der_len(const hal_ecdsa_key_t * const key) } /* - * Read private key in RFC 5915 ASN.1 DER format. + * Read private key in PKCS #8 PrivateKeyInfo DER format (RFC 5208, RFC 5915). * * This is hand-coded, and is approaching the limit where one should * probably be using an ASN.1 compiler like asn1c instead. @@ -1407,48 +1383,47 @@ hal_error_t hal_ecdsa_private_key_from_der(hal_ecdsa_key_t **key_, memset(keybuf, 0, keybuf_len); key->type = HAL_KEY_TYPE_EC_PRIVATE; - size_t hlen, vlen; + size_t hlen, vlen, alg_oid_len, curve_oid_len, privkey_len; + const uint8_t *alg_oid, *curve_oid, *privkey; hal_error_t err; - if ((err = hal_asn1_decode_header(ASN1_SEQUENCE, der, der_len, &hlen, &vlen)) != HAL_OK) + if ((err = hal_asn1_decode_pkcs8_privatekeyinfo(&alg_oid, &alg_oid_len, + &curve_oid, &curve_oid_len, + &privkey, &privkey_len, + der, der_len)) != HAL_OK) return err; - const uint8_t * const der_end = der + hlen + vlen; - const uint8_t *d = der + hlen; - const ecdsa_curve_t *curve = NULL; + if (alg_oid_len != hal_asn1_oid_ecPublicKey_len || + memcmp(alg_oid, hal_asn1_oid_ecPublicKey, alg_oid_len) != 0 || + oid_to_curve(&key->curve, curve_oid, curve_oid_len) == NULL) + return HAL_ERROR_ASN1_PARSE_FAILED; + + if ((err = hal_asn1_decode_header(ASN1_SEQUENCE, privkey, privkey_len, &hlen, &vlen)) != HAL_OK) + return err; + + const uint8_t * const der_end = privkey + hlen + vlen; + const uint8_t *d = privkey + hlen; fp_int version[1] = INIT_FP_INT; if ((err = hal_asn1_decode_integer(version, d, &hlen, vlen)) != HAL_OK) - goto fail; + return err; if (fp_cmp_d(version, 1) != FP_EQ) - lose(HAL_ERROR_ASN1_PARSE_FAILED); + return HAL_ERROR_ASN1_PARSE_FAILED; d += hlen; if ((err = hal_asn1_decode_header(ASN1_OCTET_STRING, d, der_end - d, &hlen, &vlen)) != HAL_OK) - return err; + goto fail; d += hlen; fp_read_unsigned_bin(key->d, unconst_uint8_t(d), vlen); d += vlen; - if ((err = hal_asn1_decode_header(ASN1_EXPLICIT_0, d, der_end - d, &hlen, &vlen)) != HAL_OK) - return err; - d += hlen; - if (vlen > der_end - d) - lose(HAL_ERROR_ASN1_PARSE_FAILED); - if ((err = hal_asn1_decode_header(ASN1_OBJECT_IDENTIFIER, d, vlen, &hlen, &vlen)) != HAL_OK) - return err; - d += hlen; - if ((curve = oid_to_curve(&key->curve, d, vlen)) == NULL) - lose(HAL_ERROR_ASN1_PARSE_FAILED); - d += vlen; - if ((err = hal_asn1_decode_header(ASN1_EXPLICIT_1, d, der_end - d, &hlen, &vlen)) != HAL_OK) - return err; + goto fail; d += hlen; if (vlen > der_end - d) lose(HAL_ERROR_ASN1_PARSE_FAILED); if ((err = hal_asn1_decode_header(ASN1_BIT_STRING, d, vlen, &hlen, &vlen)) != HAL_OK) - return err; + goto fail; d += hlen; if (vlen < 4 || (vlen & 1) != 0 || *d++ != 0x00 || *d++ != 0x04) lose(HAL_ERROR_ASN1_PARSE_FAILED); @@ -1474,8 +1449,6 @@ hal_error_t hal_ecdsa_private_key_from_der(hal_ecdsa_key_t **key_, * Write public key in SubjectPublicKeyInfo format, see RFCS 5280 and 5480. */ -static const uint8_t oid_ecPublicKey[] = { 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01 }; - hal_error_t hal_ecdsa_public_key_to_der(const hal_ecdsa_key_t * const key, uint8_t *der, size_t *der_len, const size_t der_max) { @@ -1508,7 +1481,7 @@ hal_error_t hal_ecdsa_public_key_to_der(const hal_ecdsa_key_t * const key, assert(d < der + der_max); } - return hal_asn1_encode_spki(oid_ecPublicKey, sizeof(oid_ecPublicKey), + return hal_asn1_encode_spki(hal_asn1_oid_ecPublicKey, hal_asn1_oid_ecPublicKey_len, curve->oid, curve->oid_len, der, ecpoint_len, der, der_len, der_max); @@ -1551,7 +1524,8 @@ hal_error_t hal_ecdsa_public_key_from_der(hal_ecdsa_key_t **key_, return err; if (alg_oid == NULL || curve_oid == NULL || pubkey == NULL || - alg_oid_len != sizeof(oid_ecPublicKey) || memcmp(alg_oid, oid_ecPublicKey, alg_oid_len) != 0 || + alg_oid_len != hal_asn1_oid_ecPublicKey_len || + memcmp(alg_oid, hal_asn1_oid_ecPublicKey, alg_oid_len) != 0 || (curve = oid_to_curve(&key->curve, curve_oid, curve_oid_len)) == NULL || pubkey_len < 3 || (pubkey_len & 1) == 0 || pubkey[0] != 0x04 || pubkey_len / 2 != fp_unsigned_bin_size(unconst_fp_int(curve->q))) diff --git a/pkcs8.py b/pkcs8.py new file mode 100644 index 0000000..cd45ff6 --- /dev/null +++ b/pkcs8.py @@ -0,0 +1,324 @@ +# Temporary sandbox for Python PKCS #8 hacks, probably integrate into +# test scripts, libhal.py, etc once have figured this out. +# +# Both PyCrpto and the Python ecdsa package have their own ASN.1, so +# why are we using yet another package? Because it's easier to +# understand, that's why. Perhaps once we've debugged this we'll +# recode it using one of the other packages to reduce external +# dependencies, but for now, pyasn1 wins on ease of debugging. +# +# Also see the "native" encode and decode routines in pyasn1, which +# supposedly encode and decode to built-in Python data types instead +# of the fancy types from the pyasn1 library. Might be simpler, but +# whole new mess so defer for now. + +# RFC 5208: PKCS #8 +# RFC 2313: PKCS #1.5 [rsa.c] +# RFC 5915: EC keys [ecdsa.c] + +from pyasn1.type.univ import Sequence, SetOf, Integer, OctetString, ObjectIdentifier, BitString, Any +from pyasn1.type.namedtype import NamedTypes, NamedType, OptionalNamedType +from pyasn1.type.namedval import NamedValues +from pyasn1.type.tag import Tag, tagClassContext, tagFormatSimple, tagFormatConstructed +from pyasn1.type.constraint import SingleValueConstraint +from pyasn1.codec.der.encoder import encode as DER_Encode +from pyasn1.codec.der.decoder import decode as DER_Decode + +from ecdsa import der as ECDSA_DER +from ecdsa.util import oid_ecPublicKey, encoded_oid_ecPublicKey +from ecdsa.keys import SigningKey +from ecdsa.curves import find_curve + +class AlgorithmIdentifier(Sequence): + componentType = NamedTypes( + NamedType( "algorithm", ObjectIdentifier()), + OptionalNamedType( "parameters", Any())) + +class AttributeTypeAndValue(Sequence): + componentType = NamedTypes( + NamedType( "type", ObjectIdentifier()), + NamedType( "value", Any())) + +class Attribute(Sequence): + componentType = NamedTypes( + NamedType( "type", ObjectIdentifier()), + NamedType( "vals", SetOf(componentType = Any()))) + +# RFC 5208 + +class PrivateKeyInfo(Sequence): + componentType = NamedTypes( + NamedType( "version", Integer(namedValues = NamedValues(("v1", 0))) .subtype(subtypeSpec = Integer.subtypeSpec + SingleValueConstraint(0))), + NamedType( "privateKeyAlgorithm", AlgorithmIdentifier()), + NamedType( "privateKey", OctetString()), + OptionalNamedType( "attributes", SetOf(componentType = Attribute()) .subtype(implicitTag = Tag(tagClassContext, tagFormatConstructed, 0)))) + +class EncryptedPrivateKeyInfo(Sequence): + componentType = NamedTypes( + NamedType( "encryptionAlgorithm", AlgorithmIdentifier()), + NamedType( "encryptedData", OctetString())) + +# RFC 2313 + +class RSAPrivateKey(Sequence): + componentType = NamedTypes( + NamedType( "version", Integer() .subtype(subtypeSpec = Integer.subtypeSpec + SingleValueConstraint(0))), + NamedType( "n", Integer()), + NamedType( "e", Integer()), + NamedType( "d", Integer()), + NamedType( "p", Integer()), + NamedType( "q", Integer()), + NamedType( "dP", Integer()), + NamedType( "dQ", Integer()), + NamedType( "u", Integer())) + +# RFC 5915 + +class ECPrivateKey(Sequence): + componentType = NamedTypes( + NamedType( "version", Integer(namedValues = NamedValues(("ecPrivkeyVer1", 1))) .subtype(subtypeSpec = Integer.subtypeSpec + SingleValueConstraint(1))), + NamedType( "privateKey", OctetString()), + OptionalNamedType( "parameters", ObjectIdentifier() .subtype(explicitTag = Tag(tagClassContext, tagFormatSimple, 0))), + OptionalNamedType( "publicKey", BitString() .subtype(explicitTag = Tag(tagClassContext, tagFormatSimple, 1)))) + +# Test data, generated by OpenSSL + +der_test_keys = dict( + + ec_rfc5915 = ''' + MHcCAQEEIFWaZOsQxLwZmIK4YAuf1d8S9Pnznvzcl9TjiMpvXkCYoAoGCCqGSM49 + AwEHoUQDQgAEC/8vH5bL+3KNNF/NL+VmUKZQtjA59UsGtKP6FP4ZqFc3Y7Gie77/ + lG1/L+s/6ircB1JkI8zaE3KYd7s+7IYIEQ== + '''.decode("base64"), + + ec_pkcs8 = ''' + MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgVZpk6xDEvBmYgrhg + C5/V3xL0+fOe/NyX1OOIym9eQJihRANCAAQL/y8flsv7co00X80v5WZQplC2MDn1 + Swa0o/oU/hmoVzdjsaJ7vv+UbX8v6z/qKtwHUmQjzNoTcph3uz7shggR + '''.decode("base64"), + + rsa_rfc2313 = ''' + MIIEpAIBAAKCAQEAx/N9ee3u6Z6qjw5waPhuUBYy7m6+kRfNYB8KSERGd5K2xD96 + IeyvEv+xMDA2BQ3xOummL2yAjtMZ2N7Le37nfpvtzwVWqrOHzq7OWaw/pPl1N9Lq + VSQLPoxHw3TVe69QNPVu5SeumaOGXmzTIs1pr2yVBZD/i2KYiif3BO2SgoDx7g4s + cFdg/6YiDpKYbY/yx4YN6KJxDGMM6DE0Ih8hE68flJMSIbUWIaJZo0b7XPeE9zYU + zf93VLvuYIqWYMuwTw5TSUnzeRq6ALJpf90nObduJsYEPu/i4RFlxdm5WsmOb2Tu + F7JFesEdGeT9lCxxd3CI5YTItQIBWsx0AzCS/QIDAQABAoIBAQCmC7Zvwv9cUr8g + /cSr52L0bvrstlra8wFCiYRobwp10gilAHHUKlFZXa0vb1ns6J8jZVT0nQ5FjVkx + mBMzAzgLFEJwYOaP63ckVFZYcYqI3gBR0312JvCPiL8vuZ5vkC7zS75D3qhIPlwf + ng/YHu1dGLbIYJlWjxJN6NJh7Uh1xlZcm0WAJYhJpmMIZJv2abTS4GXw4SVOyMnd + tPEgEfrK/y2PsNUPwnby6LR1cE2rxOQtb6gNCov0AAiE0BsJeE7jXa2IEl6lKoBR + ChDMAeU53pJPlcYt7ZmAgyezuEfnr4kY5Rk/nTcwTxTpzQi7Dcth8QCRqfu4wXXj + QEN7b9cBAoGBAPNjRPc/Z89jYp1IDR+R5oi7YTsLzNAIlS/t9wgrujnVdsm00xos + dd+NwvjTi7wE0fV+7u5/W9ni3077JaBGBa9+nD0iB0PgAJW+tb8HUJXABQKoTA4m + yyiAHNHgarwc1uwr+yAYqvSj7aAvIcZeXgi3qxDXEOSKuk8n57/TpPMVAoGBANJP + /9/6zxd3PdogiP0nC+piJHstexk+l4WRqGWWuRG0VTIEfBk4dQfj/UwfmTcCQxAe + D0e9EoHeVOfsv4nfOfDhGC7jHLkLpNJbc5ttgr2sZ6qIouBJ8suMDte/zZze27aU + 7epFqw0w9Y58fwRyP2u5ILYFcm+cWeplg9lY4rpJAoGBALzLs1Krn4YzDOr+Whe0 + IITN/XVFCQIStk8wo2B2MwXrvTJoDx0Ngf4AxE4qIwmdH5T0erkMmB5jK1/j12MF + DiH874tIWyRenXWLMwZU0UDoa7qM/Do6A3uOLUzsbT8wi9M1pp5WJD6S7qBED0oG + J6FRf+QXQCZYKn9+b/nQXfKlAoGADwFuPEjk5cO4Qgv4OjfC/eIqwC8qjU6N+RW/ + ciAi7ER1n6/6OsJwdzOpKvlGMUqUBl5esLuoymNWo4Wc1PV8aNdmplHGBt3x0KB9 + yyUxIt9eNiixllcwX52KoZIp1XuBKbHOl9yIq9RGcPgpB+Qu6jy3PMV+uL/rGnJL + ygIxiyECgYAwSLLuxHKGcy+oZo1vxSQlY2gOkprqK9VwjAhxGuGlJftXrL/Dkbxs + GatW0bGAyQ+VPivPl8YYhs34NCA1t1pJKczcNbHEJFN57x6AtCbHFLWB91wY96yA + 6y/Bgd45PoXryQl7+GdOAPyEYY3mq3R5vaozTraPrnD+61kpKVLJ/Q== + '''.decode("base64"), + + rsa_pkcs8 = ''' + MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDH83157e7pnqqP + DnBo+G5QFjLubr6RF81gHwpIREZ3krbEP3oh7K8S/7EwMDYFDfE66aYvbICO0xnY + 3st7fud+m+3PBVaqs4fOrs5ZrD+k+XU30upVJAs+jEfDdNV7r1A09W7lJ66Zo4Ze + bNMizWmvbJUFkP+LYpiKJ/cE7ZKCgPHuDixwV2D/piIOkphtj/LHhg3oonEMYwzo + MTQiHyETrx+UkxIhtRYholmjRvtc94T3NhTN/3dUu+5gipZgy7BPDlNJSfN5GroA + sml/3Sc5t24mxgQ+7+LhEWXF2blayY5vZO4XskV6wR0Z5P2ULHF3cIjlhMi1AgFa + zHQDMJL9AgMBAAECggEBAKYLtm/C/1xSvyD9xKvnYvRu+uy2WtrzAUKJhGhvCnXS + CKUAcdQqUVldrS9vWezonyNlVPSdDkWNWTGYEzMDOAsUQnBg5o/rdyRUVlhxioje + AFHTfXYm8I+Ivy+5nm+QLvNLvkPeqEg+XB+eD9ge7V0YtshgmVaPEk3o0mHtSHXG + VlybRYAliEmmYwhkm/ZptNLgZfDhJU7Iyd208SAR+sr/LY+w1Q/CdvLotHVwTavE + 5C1vqA0Ki/QACITQGwl4TuNdrYgSXqUqgFEKEMwB5Tnekk+Vxi3tmYCDJ7O4R+ev + iRjlGT+dNzBPFOnNCLsNy2HxAJGp+7jBdeNAQ3tv1wECgYEA82NE9z9nz2NinUgN + H5HmiLthOwvM0AiVL+33CCu6OdV2ybTTGix1343C+NOLvATR9X7u7n9b2eLfTvsl + oEYFr36cPSIHQ+AAlb61vwdQlcAFAqhMDibLKIAc0eBqvBzW7Cv7IBiq9KPtoC8h + xl5eCLerENcQ5Iq6Tyfnv9Ok8xUCgYEA0k//3/rPF3c92iCI/ScL6mIkey17GT6X + hZGoZZa5EbRVMgR8GTh1B+P9TB+ZNwJDEB4PR70Sgd5U5+y/id858OEYLuMcuQuk + 0ltzm22Cvaxnqoii4Enyy4wO17/NnN7btpTt6kWrDTD1jnx/BHI/a7kgtgVyb5xZ + 6mWD2VjiukkCgYEAvMuzUqufhjMM6v5aF7QghM39dUUJAhK2TzCjYHYzBeu9MmgP + HQ2B/gDETiojCZ0flPR6uQyYHmMrX+PXYwUOIfzvi0hbJF6ddYszBlTRQOhruoz8 + OjoDe44tTOxtPzCL0zWmnlYkPpLuoEQPSgYnoVF/5BdAJlgqf35v+dBd8qUCgYAP + AW48SOTlw7hCC/g6N8L94irALyqNTo35Fb9yICLsRHWfr/o6wnB3M6kq+UYxSpQG + Xl6wu6jKY1ajhZzU9Xxo12amUcYG3fHQoH3LJTEi3142KLGWVzBfnYqhkinVe4Ep + sc6X3Iir1EZw+CkH5C7qPLc8xX64v+sackvKAjGLIQKBgDBIsu7EcoZzL6hmjW/F + JCVjaA6Smuor1XCMCHEa4aUl+1esv8ORvGwZq1bRsYDJD5U+K8+XxhiGzfg0IDW3 + WkkpzNw1scQkU3nvHoC0JscUtYH3XBj3rIDrL8GB3jk+hevJCXv4Z04A/IRhjear + dHm9qjNOto+ucP7rWSkpUsn9 + '''.decode("base64")) + + +def decode_ecpoint(ecpoint): + return { "\x02": "compressed", "\x04": "uncompressed" }[ecpoint[0]], ecpoint[1:1+len(ecpoint)/2], ecpoint[1+len(ecpoint)/2:] + +def dumpasn1(der): + from subprocess import call + from tempfile import NamedTemporaryFile + with NamedTemporaryFile() as f: + f.write(der) + f.flush() + call(("dumpasn1", "-aop", f.name)) + +if __name__ == "__main__": + + show_manual_decode = False + + ec_rfc5915 = DER_Decode(der_test_keys["ec_rfc5915"], ECPrivateKey() )[0] + ec_pkcs8 = DER_Decode(der_test_keys["ec_pkcs8"], PrivateKeyInfo())[0] + ec_pkcs8_privateKey = DER_Decode(str(ec_pkcs8["privateKey"]), ECPrivateKey() )[0] + rsa_rfc2313 = DER_Decode(der_test_keys["rsa_rfc2313"], RSAPrivateKey() )[0] + rsa_pkcs8 = DER_Decode(der_test_keys["rsa_pkcs8"], PrivateKeyInfo())[0] + rsa_pkcs8_privateKey = DER_Decode(str(rsa_pkcs8["privateKey"]), RSAPrivateKey() )[0] + + print + print "EC RFC 5915" + print ec_rfc5915.prettyPrint() + + if show_manual_decode: + print + compressed, Qx, Qy = decode_ecpoint(ec_rfc5915["publicKey"].asOctets()) + print "version: ", ec_rfc5915["version"] + print "privateKey:", str(ec_rfc5915["privateKey"]).encode("hex") + print "parameters:", ec_rfc5915["parameters"] + print "publicKey: ", compressed + print " Qx: ", Qx.encode("hex") + print " Qy: ", Qy.encode("hex") + + # This works, and lets .prettyPrint() display the ANY content properly, + # but it breaks some of the key hackery we do after all this display stuff. + #ec_pkcs8["privateKeyAlgorithm"]["parameters"] = DER_Decode(ec_pkcs8["privateKeyAlgorithm"]["parameters"])[0] + + print + print "EC PKCS #8" + print ec_pkcs8.prettyPrint() + print ec_pkcs8_privateKey.prettyPrint() + + if show_manual_decode: + print + compressed, Qx, Qy = decode_ecpoint(ec_pkcs8_privateKey["publicKey"].asOctets()) + print "version: ", ec_pkcs8["version"] + print "privateKeyAlgorithm:", ec_pkcs8["privateKeyAlgorithm"][0] + print " ", DER_Decode(ec_pkcs8["privateKeyAlgorithm"]["parameters"])[0] + print "privateKey:" + print " version: ", ec_pkcs8_privateKey["version"] + print " privateKey:", str(ec_pkcs8_privateKey["privateKey"]).encode("hex") + print " parameters:", ec_pkcs8_privateKey["parameters"] + print " publicKey: ", compressed + print " Qx: ", Qx.encode("hex") + print " Qy: ", Qy.encode("hex") + + print + print "RSA RFC 2313" + print rsa_rfc2313.prettyPrint() + + if show_manual_decode: + print + print "version:", rsa_rfc2313["version"] + print " n:", rsa_rfc2313["n"] + print " e:", rsa_rfc2313["e"] + print " d:", rsa_rfc2313["d"] + print " p:", rsa_rfc2313["p"] + print " q:", rsa_rfc2313["q"] + print " dP:", rsa_rfc2313["dP"] + print " dQ:", rsa_rfc2313["dQ"] + print " u:", rsa_rfc2313["u"] + + #rsa_pkcs8["privateKeyAlgorithm"]["parameters"] = DER_Decode(rsa_pkcs8["privateKeyAlgorithm"]["parameters"])[0] + + print + print "RSA PKCS #8" + print rsa_pkcs8.prettyPrint() + print rsa_pkcs8_privateKey.prettyPrint() + + if show_manual_decode: + print + print "version: ", rsa_pkcs8["version"] + print "privateKeyAlgorithm:", rsa_pkcs8["privateKeyAlgorithm"][0] + print "privateKey:" + print " version:", rsa_pkcs8_privateKey["version"] + print " n:", rsa_pkcs8_privateKey["n"] + print " e:", rsa_pkcs8_privateKey["e"] + print " d:", rsa_pkcs8_privateKey["d"] + print " p:", rsa_pkcs8_privateKey["p"] + print " q:", rsa_pkcs8_privateKey["q"] + print " dP:", rsa_pkcs8_privateKey["dP"] + print " dQ:", rsa_pkcs8_privateKey["dQ"] + print " u:", rsa_pkcs8_privateKey["u"] + + # Generate PKCS #8 from ECPrivateKey and check against static data + p8 = PrivateKeyInfo() + ec = ECPrivateKey() + ec["version"] = ec_rfc5915["version"] + ec["privateKey"] = ec_rfc5915["privateKey"] + ec["publicKey"] = ec_rfc5915["publicKey"] + p8["version"] = 0 + p8["privateKeyAlgorithm"] = AlgorithmIdentifier() + p8["privateKeyAlgorithm"]["algorithm"] = "1.2.840.10045.2.1" + p8["privateKeyAlgorithm"]["parameters"] = ObjectIdentifier(ec_rfc5915["parameters"]) + p8["privateKey"] = DER_Encode(ec) + der = DER_Encode(p8) + #print; dumpasn1(der) + #print; dumpasn1(der_test_keys["ec_pkcs8"]) + print; print "Reencoded PKCS #8 {} static data".format("matches" if der == der_test_keys["ec_pkcs8"] else "doesn't match") + + # Try doing same thing with ecdsa package ASN.1 utilities. + sk = SigningKey.from_der(der_test_keys["ec_rfc5915"]) + vk = ECDSA_DER.encode_bitstring("\x00\x04" + sk.get_verifying_key().to_string()) + ec = ECDSA_DER.encode_sequence(ECDSA_DER.encode_integer(1), + ECDSA_DER.encode_octet_string(sk.to_string()), + ECDSA_DER.encode_constructed(1, vk)) + p8 = ECDSA_DER.encode_sequence(ECDSA_DER.encode_integer(0), + ECDSA_DER.encode_sequence(encoded_oid_ecPublicKey, + sk.curve.encoded_oid), + ECDSA_DER.encode_octet_string(ec)) + print; print "ECDSA-library PKCS #8 encoding {} pyasn1 PKCS #8 encoding".format("matches" if p8 == der_test_keys["ec_pkcs8"] else "doesn't match") + + # Generate ECPrivateKey from PKCS #8 and check against static data + ec = ECPrivateKey() + ec["version"] = ec_pkcs8_privateKey["version"] + ec["privateKey"] = ec_pkcs8_privateKey["privateKey"] + ec["parameters"] = str(DER_Decode(ec_pkcs8["privateKeyAlgorithm"]["parameters"])[0]) + ec["publicKey"] = ec_pkcs8_privateKey["publicKey"] + der = DER_Encode(ec) + #print; dumpasn1(der) + #print; dumpasn1(der_test_keys["ec_rfc5915"]) + print; print "Reencoded PKCS #8 {} static data".format("matches" if der == der_test_keys["ec_rfc5915"] else "doesn't match") + + # Paranoia: Make sure we really can load the RFC 5915 we just generated. + sk = SigningKey.from_der(der) + print; print "ECDSA Python library parse of reencoded PKCS #8 data: {!r}".format(sk) + + # Same thing with ecdsa package ASN.1 utilities. + car, cdr = ECDSA_DER.remove_sequence(der_test_keys["ec_pkcs8"]) + assert cdr == "" + version, cdr = ECDSA_DER.remove_integer(car) + assert version == 0 + car, ec = ECDSA_DER.remove_sequence(cdr) + oid, cdr = ECDSA_DER.remove_object(car) + assert oid == oid_ecPublicKey + oid, cdr = ECDSA_DER.remove_object(cdr) + curve = find_curve(oid) + assert cdr == "" + car, cdr = ECDSA_DER.remove_octet_string(ec) + assert cdr == "" + car, cdr = ECDSA_DER.remove_sequence(car) + assert cdr == "" + version, cdr = ECDSA_DER.remove_integer(car) + assert version == 1 + privkey, cdr = ECDSA_DER.remove_octet_string(cdr) + tag, car, cdr = ECDSA_DER.remove_constructed(cdr) + assert tag == 1 + assert cdr == "" + pubkey, cdr = ECDSA_DER.remove_bitstring(car) + assert cdr == "" + assert pubkey[:2] == "\x00\x04" + sk = SigningKey.from_string(privkey, curve) + print; print "ECDSA-library PKCS #8 decoding {} pyasn1 PKCS #8 decoding".format( + "matches" if der == sk.to_der() else "doesn't match") @@ -673,7 +673,7 @@ hal_error_t hal_rsa_key_gen(const hal_core_t *core, /* * Just enough ASN.1 to read and write PKCS #1.5 RSAPrivateKey syntax - * (RFC 2313 section 7.2). + * (RFC 2313 section 7.2) wrapped in a PKCS #8 PrivateKeyInfo (RFC 5208). * * RSAPrivateKey fields in the required order. */ @@ -709,15 +709,12 @@ hal_error_t hal_rsa_private_key_to_der(const hal_rsa_key_t * const key, RSAPrivateKey_fields; #undef _ - /* - * Encode header. - */ - - if ((err = hal_asn1_encode_header(ASN1_SEQUENCE, vlen, der, &hlen, der_max)) != 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 ((err = hal_asn1_encode_pkcs8_privatekeyinfo(hal_asn1_oid_rsaEncryption, hal_asn1_oid_rsaEncryption_len, + NULL, 0, NULL, hlen + vlen, NULL, der_len, der_max)) != HAL_OK) + return err; if (der == NULL) return HAL_OK; @@ -726,13 +723,18 @@ hal_error_t hal_rsa_private_key_to_der(const hal_rsa_key_t * const key, * Encode data. */ - der += hlen; + if ((err = hal_asn1_encode_header(ASN1_SEQUENCE, vlen, der, &hlen, der_max)) != HAL_OK) + return err; -#define _(x) { size_t n; if ((err = hal_asn1_encode_integer(x, der, &n, vlen)) != HAL_OK) return err; der += n; vlen -= n; } + uint8_t *d = der + hlen; + memset(d, 0, vlen); + +#define _(x) { size_t n; if ((err = hal_asn1_encode_integer(x, d, &n, vlen)) != HAL_OK) return err; d += n; vlen -= n; } RSAPrivateKey_fields; #undef _ - return HAL_OK; + return hal_asn1_encode_pkcs8_privatekeyinfo(hal_asn1_oid_rsaEncryption, hal_asn1_oid_rsaEncryption_len, + NULL, 0, der, d - der, der, der_len, der_max); } size_t hal_rsa_private_key_to_der_len(const hal_rsa_key_t * const key) @@ -754,21 +756,33 @@ hal_error_t hal_rsa_private_key_from_der(hal_rsa_key_t **key_, key->type = HAL_KEY_TYPE_RSA_PRIVATE; - hal_error_t err = HAL_OK; - size_t hlen, vlen; + size_t hlen, vlen, alg_oid_len, curve_oid_len, privkey_len; + const uint8_t *alg_oid, *curve_oid, *privkey; + hal_error_t err; - if ((err = hal_asn1_decode_header(ASN1_SEQUENCE, der, der_len, &hlen, &vlen)) != HAL_OK) + if ((err = hal_asn1_decode_pkcs8_privatekeyinfo(&alg_oid, &alg_oid_len, + &curve_oid, &curve_oid_len, + &privkey, &privkey_len, + der, der_len)) != HAL_OK) return err; - der += hlen; + if (alg_oid_len != hal_asn1_oid_rsaEncryption_len || + memcmp(alg_oid, hal_asn1_oid_rsaEncryption, alg_oid_len) != 0 || + curve_oid_len != 0) + return HAL_ERROR_ASN1_PARSE_FAILED; + + if ((err = hal_asn1_decode_header(ASN1_SEQUENCE, privkey, privkey_len, &hlen, &vlen)) != HAL_OK) + return err; + + const uint8_t *d = privkey + hlen; fp_int version[1] = INIT_FP_INT; -#define _(x) { size_t i; if ((err = hal_asn1_decode_integer(x, der, &i, vlen)) != HAL_OK) return err; der += i; vlen -= i; } +#define _(x) { size_t n; if ((err = hal_asn1_decode_integer(x, d, &n, vlen)) != HAL_OK) return err; d += n; vlen -= n; } RSAPrivateKey_fields; #undef _ - if (fp_cmp_d(version, 0) != FP_EQ) + if (d != privkey + privkey_len || !fp_iszero(version)) return HAL_ERROR_ASN1_PARSE_FAILED; *key_ = key; @@ -780,8 +794,6 @@ hal_error_t hal_rsa_private_key_from_der(hal_rsa_key_t **key_, * ASN.1 public keys in SubjectPublicKeyInfo form, see RFCs 2313, 4055, and 5280. */ -static const uint8_t oid_rsaEncryption[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01 }; - hal_error_t hal_rsa_public_key_to_der(const hal_rsa_key_t * const key, uint8_t *der, size_t *der_len, const size_t der_max) { @@ -810,7 +822,7 @@ hal_error_t hal_rsa_public_key_to_der(const hal_rsa_key_t * const key, return err; } - return hal_asn1_encode_spki(oid_rsaEncryption, sizeof(oid_rsaEncryption), + return hal_asn1_encode_spki(hal_asn1_oid_rsaEncryption, hal_asn1_oid_rsaEncryption_len, NULL, 0, der, hlen + vlen, der, der_len, der_max); @@ -843,7 +855,7 @@ hal_error_t hal_rsa_public_key_from_der(hal_rsa_key_t **key_, return err; if (null != NULL || null_len != 0 || alg_oid == NULL || - alg_oid_len != sizeof(oid_rsaEncryption) || memcmp(alg_oid, oid_rsaEncryption, alg_oid_len) != 0) + alg_oid_len != hal_asn1_oid_rsaEncryption_len || memcmp(alg_oid, hal_asn1_oid_rsaEncryption, alg_oid_len) != 0) return HAL_ERROR_ASN1_PARSE_FAILED; size_t len, hlen, vlen; diff --git a/unit-tests.py b/unit-tests.py index 4fd91e6..f461a0e 100644 --- a/unit-tests.py +++ b/unit-tests.py @@ -57,9 +57,11 @@ except ImportError: try: + from ecdsa import der as ECDSA_DER from ecdsa.keys import SigningKey as ECDSA_SigningKey, VerifyingKey as ECDSA_VerifyingKey from ecdsa.ellipticcurve import Point - from ecdsa.curves import NIST256p, NIST384p, NIST521p + from ecdsa.curves import NIST256p, NIST384p, NIST521p, find_curve as ECDSA_find_curve + from ecdsa.util import oid_ecPublicKey if not pycrypto_loaded: from hashlib import sha256 as SHA256, sha384 as SHA384, sha512 as SHA512 ecdsa_loaded = True @@ -916,8 +918,8 @@ class PreloadedRSAKey(PreloadedKey): if pycrypto_loaded: k1 = RSA.importKey(pem) k2 = k1.publickey() - cls(HAL_KEY_TYPE_RSA_PRIVATE, keylen, k1, k1.exportKey("DER"), keylen = keylen) - cls(HAL_KEY_TYPE_RSA_PUBLIC, keylen, k2, k2.exportKey("DER"), keylen = keylen) + cls(HAL_KEY_TYPE_RSA_PRIVATE, keylen, k1, k1.exportKey(format = "DER", pkcs = 8), keylen = keylen) + cls(HAL_KEY_TYPE_RSA_PUBLIC, keylen, k2, k2.exportKey(format = "DER" ), keylen = keylen) def sign(self, text, hash): return PKCS1_v1_5.PKCS115_SigScheme(self.obj).sign(hash(text)) @@ -927,12 +929,35 @@ class PreloadedRSAKey(PreloadedKey): class PreloadedECKey(PreloadedKey): + @staticmethod + def _check(condition): + if not condition: + raise ECDSA_DER.UnexpectedDER() + @classmethod def importKey(cls, curve, pem): if ecdsa_loaded: - k1 = ECDSA_SigningKey.from_pem(pem) + der = ECDSA_DER.unpem(pem) + car, cdr = ECDSA_DER.remove_sequence(der) + cls._check(cdr == "") + version, cdr = ECDSA_DER.remove_integer(car) + cls._check(version == 0) + algid, pkinfo = ECDSA_DER.remove_sequence(cdr) + oid, cdr = ECDSA_DER.remove_object(algid) + cls._check(oid == oid_ecPublicKey) + oid, cdr = ECDSA_DER.remove_object(cdr) + sk_curve = ECDSA_find_curve(oid) + cls._check(cdr == "") + car, cdr = ECDSA_DER.remove_octet_string(pkinfo) + cls._check(cdr == "") + car, cdr = ECDSA_DER.remove_sequence(car) + cls._check(cdr == "") + version, cdr = ECDSA_DER.remove_integer(car) + cls._check(version == 1) + privkey, cdr = ECDSA_DER.remove_octet_string(cdr) + k1 = ECDSA_SigningKey.from_string(privkey, sk_curve) k2 = k1.get_verifying_key() - cls(HAL_KEY_TYPE_EC_PRIVATE, curve, k1, k1.to_der(), curve = curve) + cls(HAL_KEY_TYPE_EC_PRIVATE, curve, k1, der, curve = curve) cls(HAL_KEY_TYPE_EC_PUBLIC, curve, k2, k2.to_der(), curve = curve) def sign(self, text, hash): @@ -944,137 +969,141 @@ class PreloadedECKey(PreloadedKey): # openssl genrsa 1024 PreloadedRSAKey.importKey(1024, '''\ ------BEGIN RSA PRIVATE KEY----- -MIICXQIBAAKBgQC95QlDOvlQhdCe/a7eIoX9SGPVfXfA8/62ilnF+NcwLrhxkr2R -4EVQB65+9AbxqM8Hqol6fhZzmDs48cl2tOFGJpE8iMhiFm4i6SGl2RXYaG0xi+lJ -FrXXCLFQovIEMuukBE129wra1xIB72tYR14lu8REX+Mhpbuz44M1jlCrlQIDAQAB -AoGAeU928l8bZIiH9PnlG318kYkMVhd4SGjXQK/zl9hXSC2goNV4i1d1kCHIJMwq -H3mTALe+aeVg3GnU85Tq+g2llzogoyXl8q902KbvImrM/XSbsue9/oj0OSgw+jKB -faFzX6FxAtNV5pmU9QiwauBIl/3yPCF9ifim5zg+pWCqLaECQQD59Z/R6TrTHxp6 -w2vH4CJyP5KORcf+eMa50SAriMVBXsJzsBiLLVxKIZfWbQn9gytJqJZKmIHezZQm -dyam84fpAkEAwnvSF27RhxLXE037+t7k5MZti6BfNTeUBrwffteepL6qax9HK+h9 -IQZ1vfNIqjZm8i7kQQyy4L8tRnk8mjZmzQJBAIUwfXWTilW+yBRMFx1M7+3itAv9 -YODWqEWRCkxIN5tqi8CrP5jBleCmX8rRFTaxcxpvq42aD/GRp3SLntvs/ikCQCSg -GOKc1gyv+Z0DFK8cBtMmoz6mRwfInbHe/7dtd8zis0lVLJwSPm5Xvxi0ljyn3h9B -wW6Wq6Ezn50j+8u27wkCQQCcIFE01BDAdtFHtTJ3aaEM9IdMCYrcJ0I/Y0NTE2M6 -lsTSiPyQjc4dQQJxFduvWHLx28bx+l7FTav7FaKntCJo ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAL3lCUM6+VCF0J79 +rt4ihf1IY9V9d8Dz/raKWcX41zAuuHGSvZHgRVAHrn70BvGozweqiXp+FnOYOzjx +yXa04UYmkTyIyGIWbiLpIaXZFdhobTGL6UkWtdcIsVCi8gQy66QETXb3CtrXEgHv +a1hHXiW7xERf4yGlu7PjgzWOUKuVAgMBAAECgYB5T3byXxtkiIf0+eUbfXyRiQxW +F3hIaNdAr/OX2FdILaCg1XiLV3WQIcgkzCofeZMAt75p5WDcadTzlOr6DaWXOiCj +JeXyr3TYpu8iasz9dJuy573+iPQ5KDD6MoF9oXNfoXEC01XmmZT1CLBq4EiX/fI8 +IX2J+KbnOD6lYKotoQJBAPn1n9HpOtMfGnrDa8fgInI/ko5Fx/54xrnRICuIxUFe +wnOwGIstXEohl9ZtCf2DK0molkqYgd7NlCZ3Jqbzh+kCQQDCe9IXbtGHEtcTTfv6 +3uTkxm2LoF81N5QGvB9+156kvqprH0cr6H0hBnW980iqNmbyLuRBDLLgvy1GeTya +NmbNAkEAhTB9dZOKVb7IFEwXHUzv7eK0C/1g4NaoRZEKTEg3m2qLwKs/mMGV4KZf +ytEVNrFzGm+rjZoP8ZGndIue2+z+KQJAJKAY4pzWDK/5nQMUrxwG0yajPqZHB8id +sd7/t213zOKzSVUsnBI+ble/GLSWPKfeH0HBbparoTOfnSP7y7bvCQJBAJwgUTTU +EMB20Ue1MndpoQz0h0wJitwnQj9jQ1MTYzqWxNKI/JCNzh1BAnEV269YcvHbxvH6 +XsVNq/sVoqe0Img= +-----END PRIVATE KEY----- ''') # openssl genrsa 2048 PreloadedRSAKey.importKey(2048, '''\ ------BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEAsbvq6syhDXD/OMVAuLoMceGQLUIiezfShVqFfyMqADjqhFRW -Wbonn0XV9ZkypU4Ib9n6PtLATNaefhpsUlI4s+20YTlQ7GiwJ9p97/N1o1u060ja -4LdqhfYtn8GZX+JAfa5NqpmLKCJ58XJ3q28MPLRwYp5yKckjkzchZHFyjs1W7r5a -JfeJ/vsQusX3klmCehJ1jxSHPh8o6lTjFMnBK8t360YTu0UGK/RUcEAYO7l7FWjd -8PjZfawXIrOAhCLkVvDFfpsl2oyFIL9d1QE87WdyyZXAtWLs62gnX+kiBq9gUhu5 -GsgcQifHBcRiGZfH0TRIMgIsSjsorzHqJ9uoQwIDAQABAoIBAGqzx5/5A8NfEEpT -2bxNLcV8xqL1LmBNLh0TMEwYn1GM2fZh74lkwf7T3VTaCVbGlzgXZC4tNneq7XIF -iPyPEi2rSnyH/XZAj2kNukfBIOHW37HVhloco14TYmajwuGWomMRrtz521pYAF+c -+g042N7k8Qez2hQOBkaOdYSouz7RNdJUGUocRhcSkh+QZTBwtQxrkuhhHN+zkIri -+Q09hF2hAliHrh6mow8ci0gRsXnZzsdJfTX8CasHWTIll4gfrvWnUY7iYqB6ynRU -YN+7IgQXMUFLziIlH1qN+DlEYdznsgAPSS3JdTWh0cvjiO8wTFAnOIdsj+BpKoDB -PK2zzDkCgYEA3TP8h4Ds/y1tDijE3Sarrg0vWuY97sJmAla4qFHH4hscZ84NDzTM -I/ohLPJgpeR2MaBqZmVk9UFrd3rdt3/lX6kSO7Kffa9rVgfOB4CqJ4joso3j0qY8 -V/iVBcDcD1h4aXCRX2tMJICUTgVU/N8/2wBEElcOUjZHGlcHmbHndlUCgYEAzbFm -ttPuIHrYHkmOm/DjYB65+WD8gfPMdeUbnx+yIt5xwimIbq1qWzl4++goTAAyaU/7 -qM9IfveRue0B7yjnPa8fjN+CcXMGM6a3BIqeIv1icfgjHxlt7D+64FpENWXHvFE0 -MhRliINfkTHm+U4+1s0045a+bLdTbfVly1gATDcCgYEAyOaoWmFL3k7hl1SLx9eR -YVj0Q3iNk0XX5BPjTmxIQCEjYVwRHFh1d897Rhk0kja26kepmypH0UADXNaofDqa -lpE10CZhGIOz1sTr6ICBCbscrN6VpgH5GGTa5AjPVNijNBBa1/DZjOWCzIGnOKuC -kWLicE3E4gIN/exBKOQdNqkCgYEAjA5PMg38BoGexoCvad8L81b4qqUvSg0HGv91 -X1Plp3hvXRWKoFHUKWlox528UoOPz8V2ReteIZXQ1BhdSMtBKO8lPHa0CyuW/XR3 -CdCY/Jorfg7HW1WlU0fRpxHPf8xdxAxGzhK1T86kM+kWrIpqnzf62zy5TK1HUYfW -WC8DhOECgYBzU8hIA0PU7aRPUs0o9MO9XcvVPvdX6UOKdNb9CnBMudS/chKHJUYP -d0fFAiVaRX0JMQ0RSrenxCqfWVtW3T3wFYNHB/IFRIUT3I44wwXJTNOeoi3FDTMx -EQfc0UFoFHyc3mYEKR4zHheqQG5OFBN89LqG3S+O69vc1qwCvNKL+Q== ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCxu+rqzKENcP84 +xUC4ugxx4ZAtQiJ7N9KFWoV/IyoAOOqEVFZZuiefRdX1mTKlTghv2fo+0sBM1p5+ +GmxSUjiz7bRhOVDsaLAn2n3v83WjW7TrSNrgt2qF9i2fwZlf4kB9rk2qmYsoInnx +cnerbww8tHBinnIpySOTNyFkcXKOzVbuvlol94n++xC6xfeSWYJ6EnWPFIc+Hyjq +VOMUycEry3frRhO7RQYr9FRwQBg7uXsVaN3w+Nl9rBcis4CEIuRW8MV+myXajIUg +v13VATztZ3LJlcC1YuzraCdf6SIGr2BSG7kayBxCJ8cFxGIZl8fRNEgyAixKOyiv +Meon26hDAgMBAAECggEAarPHn/kDw18QSlPZvE0txXzGovUuYE0uHRMwTBifUYzZ +9mHviWTB/tPdVNoJVsaXOBdkLi02d6rtcgWI/I8SLatKfIf9dkCPaQ26R8Eg4dbf +sdWGWhyjXhNiZqPC4ZaiYxGu3PnbWlgAX5z6DTjY3uTxB7PaFA4GRo51hKi7PtE1 +0lQZShxGFxKSH5BlMHC1DGuS6GEc37OQiuL5DT2EXaECWIeuHqajDxyLSBGxednO +x0l9NfwJqwdZMiWXiB+u9adRjuJioHrKdFRg37siBBcxQUvOIiUfWo34OURh3Oey +AA9JLcl1NaHRy+OI7zBMUCc4h2yP4GkqgME8rbPMOQKBgQDdM/yHgOz/LW0OKMTd +JquuDS9a5j3uwmYCVrioUcfiGxxnzg0PNMwj+iEs8mCl5HYxoGpmZWT1QWt3et23 +f+VfqRI7sp99r2tWB84HgKoniOiyjePSpjxX+JUFwNwPWHhpcJFfa0wkgJROBVT8 +3z/bAEQSVw5SNkcaVweZsed2VQKBgQDNsWa20+4getgeSY6b8ONgHrn5YPyB88x1 +5RufH7Ii3nHCKYhurWpbOXj76ChMADJpT/uoz0h+95G57QHvKOc9rx+M34JxcwYz +prcEip4i/WJx+CMfGW3sP7rgWkQ1Zce8UTQyFGWIg1+RMeb5Tj7WzTTjlr5st1Nt +9WXLWABMNwKBgQDI5qhaYUveTuGXVIvH15FhWPRDeI2TRdfkE+NObEhAISNhXBEc +WHV3z3tGGTSSNrbqR6mbKkfRQANc1qh8OpqWkTXQJmEYg7PWxOvogIEJuxys3pWm +AfkYZNrkCM9U2KM0EFrX8NmM5YLMgac4q4KRYuJwTcTiAg397EEo5B02qQKBgQCM +Dk8yDfwGgZ7GgK9p3wvzVviqpS9KDQca/3VfU+WneG9dFYqgUdQpaWjHnbxSg4/P +xXZF614hldDUGF1Iy0Eo7yU8drQLK5b9dHcJ0Jj8mit+DsdbVaVTR9GnEc9/zF3E +DEbOErVPzqQz6RasimqfN/rbPLlMrUdRh9ZYLwOE4QKBgHNTyEgDQ9TtpE9SzSj0 +w71dy9U+91fpQ4p01v0KcEy51L9yEoclRg93R8UCJVpFfQkxDRFKt6fEKp9ZW1bd +PfAVg0cH8gVEhRPcjjjDBclM056iLcUNMzERB9zRQWgUfJzeZgQpHjMeF6pAbk4U +E3z0uobdL47r29zWrAK80ov5 +-----END PRIVATE KEY----- ''') # openssl genrsa 4096 PreloadedRSAKey.importKey(4096, '''\ ------BEGIN RSA PRIVATE KEY----- -MIIJKAIBAAKCAgEAzWpYSQt+DrUNI+EJT/ko92wM2POfFnmm3Kc34nmuK6sez0DJ -r9Vib9R5K46RNgqcUdAodjU6cy3/MZA53SqP7RwR/LQtWmK2a+T4iey2vQZ0iCDA -2NI4gjgmCAjZnOD/m5yUXjCig/wJ8pGXolg8oHnvdeLg1joIOSF9OudLrI6aJnDg -OfdegzmCWXmWl7TXrqHVIWZhZZF7qQZRso6ZQ1/8mjpvVD0drASBxMnIzvpe4ynr -Y2NB807X/D5bbScp292ZKTNf5unPN1SsFy5ymzfLZrfNksYef6xPXcVr6OiObi49 -De8e11aNPj6fgLzzqAu1rjjrDkgvXx5G7gPJXq1aq6uxB2cKMrRS+ivmyC8vQlzP -lQwW20oYeeOfCg7ddNAJcu3jNTuNJaZdhc9szpVhV8DXZoXe/RzUNjZH7wUqueHy -fpbLwS+h3McJqrbWFdCQBivZnoI05cF2JIHEeR3S0Gyo2/IheNeFX2Tt8oDnHY4a -olRHiR5CMdM8UoGSxR9Y12fZ9dcqdCH3d6wDAsBDHTCE8ZIwFwhW6iA+g54YE3X7 -BlsgWr60poCDgH+CJjh0VDVxqL7r+w76sD9WAQMa7Gb+Mp2XCYnIZPXTrsmwVbZ9 -s5vFXUEODYom6qBlbZB8gyZzee5Skc1jx2fnmqxRtflA4W3xVAQFof2rFiUCAwEA -AQKCAgBxhQXJSFqf0hqy61h0I+Qp6EKpWuleSFiYtKjDti803tql+s37KFfAKZHV -KnLBhNeitwDFYuEsag0P3P69ZRopFUwzdXdi7g6WTfG0d2b9y6V23XL14Cduf400 -/38TnZxk6QFtlD8b5ZuxvBgqlczbeseFRJ6whV2qBQHqHYzKjfxOpi6kmjpXFt8c -h39b04smbTUVwjitIttOK7nWjcvRWiiFKyn/Sc8uE0eL81/QUrlBnRcC1AXMapQe -SG/KQMx3P123UTb8q9XiZB6+qOKZORplZ8pqBKcyM42g6suZ6XtdFJyVKMLIioKA -FaecQ8/73IzI/ZeZSvcy/85/FwSfGjHD7C7vL9kfg77no+IvHYlBYiIqtTddpQH5 -LGJAJnOGtk047/OjTmL8QyylvDAv8jBeZZdbOX7L+8jk5DbHmfUcDjvBS9g+Fbfk -jDurphrp1dHn/YgaA27NZs87TPWX1aVPiOlXEhO9SHHiiKCHDpBzV1gW/eiho33s -+uEr57ZoakzonN/zNb7KqHUO/ZGwMg+V9bVIgThqbdgmxNz7JFz14CN79yPmW5QT -1P1v7a6xWaZTALe2HGvy0B+iRzhLpay1tI4O/omPj9vUzVJwGHztVt0RddcmA9wV -Y3qglRNl+YvNlm6BUn8KwPIqki8JoioA8J1EQ5mz/K0fbrzcOQKCAQEA8TCqq0pb -mfxtsf42zhsSUw1VdcCIG0IYcSWxIiCfujryAQX1tmstZeRchlykXmdO+JDcpvMy -BKBD7188JEWjCX1IRRtHxTJ5WG+pE8sNPLNL8eZVZ+CEbNjVk4dtWGLwyNm+rQkM -NmOlm+7ZHdezBXljZOeqZbdsTSDQcGYG8JxlvLpAN60pjIGvTdTrdnksMhB4PK+l -7KtyEVDWXU/VT6kqhP3Ri1doHv/81BplgfjEJM8ZxmasfP4SlJ1olKqsHMFSrclj -ZCAemKEexVyzg8cHm9ghj6MLQZe3gs94V6h8I2ifrBBNHMrZgYg2Db0GeyYrr+kZ -GDjT0DZp0jgyfwKCAQEA2gdTclmrfAU/67ziOJbjkMgfhBdteE1BbJDNUca0zB6q -Ju4BwNgt0cxHMbltgE2/8hWP95HIaQdh1mIgwSK93MxRbaAvAQfF3muJxvMR5Mru -DejE+IEK9eZetgkNHGWyfiFzBWHda/Z9PQkqYtRfop5qFBVAPZ4YzR5hT0j64eDQ -N/z9C0ZB6RL9EcXJgEYgGI3wP8Qsrw3JRBQN0SCVRmrEJm4WIXs+CEHOk56/VbPM -v82uwbHVghS0U9bEZvNoeq7ZQjS2tRXXRJeOgQyCNvYy670T0KvQZoDb59EbEDSz -eQZS1J7rDEBHW+VwRSJA8noMEgZdEv8AxbEF2CddWwKCAQAMwH71iXvoW1FNbNxm -70V7wKO5ExHfJxJ1wQFphYIMbZtn9HG2UFpZHcbKj9Fc8GdbewU/inIljnepC0b5 -v/jLwqT0imm0AmQqCdVNp5mukOg+BOiVEmjN/HTmVO2yE6EZbXHIYkcUBRa3dNxj -2IitjGp15k27DQSb21VJ7AsH46z5WnuUtgIRXLXxDoXYgLWWfApvYvYJ2lKwma6L -xnHHwXDvESBoFpn5sZ0jdbXSNl3geFarh7gs753534ys940cBBij+ZbYr14Owc4H -r0wKdpZvZfD4UC2DLUtVjjSVpeHSWXC/vyjkkdEIKTR6a3kRP8ZliZR7FF4Wjxnv -NGtvAoIBAEu5g6gRsNewUxUjU0boUT115ExSfrjrzC9S05z1cNH8TIic3YsHClL1 -qjyA9KE9X89K4efQgFTKNZbqGgo6cMsBQ77ZhbnL41Nu8jlhLvPR74BxOgg9eXsS -eg6rchxMzgO0xmg2J1taDwFl74zHyjeG4bz77IX6JQ8I4C9TX5+YH3lyqsiBrF6x -M6g6k9Ozh24/zhO3pPVfymmUtX/O20nLxzi5v4H9dfwULxVia33upsxvOaUYiNlX -K5J641gGbmE93UN7X4HhhhTStrHnkEpalDEASKOPKSCQ3M/U9ptYUoVURuyGDYkB -wkcOl0HLtdcBwLN59lWkr7X519fNREUCggEBAMk39k+shD2DW8ubE/LgoforwfT2 -558FPxpZ+pGwMHL3ZnLuQuiROyPyQZj/ZmmLAa2TPrwS/ssln46Y2KesejWK/0Hq -8SaFLhOjacF8u5IOOKBZvx+HOT6ctRNBVyzt9A8wu0DE6nzc5HQpm9TMXrOLuZ0L -u22yFikwoIgYpU6hBdbg1mnirZS/ZyqJV9gWB6ZYyUAUGdgBqL6euSAAqBp93qz8 -sQLesqTufT1mVZd/ndLyvjDJjNKUE0w1g/1xNtg6N5aM+7pc/DwE/s+EtCxc/858 -dQYLBHIPcw6e0FdL3nTs44BpAqcK28N5eWbe/KaZ3EA0lHRmyOQ++WgU6jo= ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +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 +w3l5Zt78ppncQDSUdGbI5D75aBTqOg== +-----END PRIVATE KEY----- ''') # openssl ecparam -genkey -name prime256v1 | openssl ec PreloadedECKey.importKey(HAL_CURVE_P256, '''\ ------BEGIN EC PRIVATE KEY----- -MHcCAQEEIPBrVhD1iFF2e8wPkPf4N1038iR8xPgku/CVOT8lcSztoAoGCCqGSM49 -AwEHoUQDQgAE3mB5BmN5Fa4fV74LsDWIpBUxktPqYGJ6WOBrjPs1HWkNU7JHO3qY -9yy+CXFSPb89GWQgb5wLtNPn4QYMj+KRTA== ------END EC PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg8GtWEPWIUXZ7zA+Q +9/g3XTfyJHzE+CS78JU5PyVxLO2hRANCAATeYHkGY3kVrh9XvguwNYikFTGS0+pg +YnpY4GuM+zUdaQ1Tskc7epj3LL4JcVI9vz0ZZCBvnAu00+fhBgyP4pFM +-----END PRIVATE KEY----- ''') # openssl ecparam -genkey -name secp384r1 | openssl ec PreloadedECKey.importKey(HAL_CURVE_P384, '''\ ------BEGIN EC PRIVATE KEY----- -MIGkAgEBBDCVGo35Hbrf3Iys7mWRIm5yjg+6vPIgzbp2jCbDyszBo+wTxmQambG4 -g8yocp4wM6+gBwYFK4EEACKhZANiAATYwa+M8T8jsNHKmMZTvPPflUIfrjuZZo1D -3kkkmN4r6cTNctjaeRdAfD0X40l4yPnGIP9ParuKVVl1y0TdQ7BS3g/Gj/LP33HD -ESP8gFDIKFCWSDX0uhmy+HsGsPwgNoY= ------END EC PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDCVGo35Hbrf3Iys7mWR +Im5yjg+6vPIgzbp2jCbDyszBo+wTxmQambG4g8yocp4wM6+hZANiAATYwa+M8T8j +sNHKmMZTvPPflUIfrjuZZo1D3kkkmN4r6cTNctjaeRdAfD0X40l4yPnGIP9ParuK +VVl1y0TdQ7BS3g/Gj/LP33HDESP8gFDIKFCWSDX0uhmy+HsGsPwgNoY= +-----END PRIVATE KEY----- ''') # openssl ecparam -genkey -name secp521r1 | openssl ec PreloadedECKey.importKey(HAL_CURVE_P521, '''\ ------BEGIN EC PRIVATE KEY----- -MIHcAgEBBEIBtf+LKhJNQEJRFQ2cGQPcviwfp9IKSnD5EFTqAPtv7/+t2FtmdHHP -/fWIlZ7jcC5N9dWy6bKGu3+FqwgZAYLpsqigBwYFK4EEACOhgYkDgYYABADdfcUe -P0oAZQ5308v5ijcg4hePvhvVi+QKcrwmE9kirXCFoYN1tzPmXZmw8lNJenrbwaNz -opJR84LBHnomGPogAQGF0aRk0jE8w1j1oMfrrzV6vCWnkh7pyzsDnrLU1HrkWeqw -ihzwMzYJgFzToDH+fCh7nrBFZZZ9P9gPYMlSM5UMeA== ------END EC PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIBtf+LKhJNQEJRFQ2c +GQPcviwfp9IKSnD5EFTqAPtv7/+t2FtmdHHP/fWIlZ7jcC5N9dWy6bKGu3+FqwgZ +AYLpsqihgYkDgYYABADdfcUeP0oAZQ5308v5ijcg4hePvhvVi+QKcrwmE9kirXCF +oYN1tzPmXZmw8lNJenrbwaNzopJR84LBHnomGPogAQGF0aRk0jE8w1j1oMfrrzV6 +vCWnkh7pyzsDnrLU1HrkWeqwihzwMzYJgFzToDH+fCh7nrBFZZZ9P9gPYMlSM5UM +eA== +-----END PRIVATE KEY----- ''') |