aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--asn1.c336
-rw-r--r--asn1_internal.h32
-rw-r--r--ecdsa.c168
-rw-r--r--pkcs8.py324
-rw-r--r--rsa.c54
-rw-r--r--unit-tests.py261
6 files changed, 939 insertions, 236 deletions
diff --git a/asn1.c b/asn1.c
index bbb049f..100dc3c 100644
--- a/asn1.c
+++ b/asn1.c
@@ -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_ */
/*
diff --git a/ecdsa.c b/ecdsa.c
index d654a78..8a31504 100644
--- a/ecdsa.c
+++ b/ecdsa.c
@@ -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")
diff --git a/rsa.c b/rsa.c
index e24b5eb..3cea42c 100644
--- a/rsa.c
+++ b/rsa.c
@@ -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-----
-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
------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-----
''')