|
@@ -9,8 +9,74 @@
|
|
|
|
|
|
#ifdef LTC_MRSA
|
|
#ifdef LTC_MRSA
|
|
|
|
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ Import an RSAPublicKey or RSAPrivateKey as defined in PKCS #1 v2.1 [two-prime only]
|
|
|
|
+
|
|
|
|
+ The `key` passed into this function has to be already initialized and will
|
|
|
|
+ NOT be free'd on error!
|
|
|
|
+
|
|
|
|
+ @param in The packet to import from
|
|
|
|
+ @param inlen It's length (octets)
|
|
|
|
+ @param key [out] Destination for newly imported key
|
|
|
|
+ @return CRYPT_OK if successful
|
|
|
|
+*/
|
|
|
|
+int rsa_import_pkcs1(const unsigned char *in, unsigned long inlen, rsa_key *key)
|
|
|
|
+{
|
|
|
|
+ int err;
|
|
|
|
+ unsigned long version = -1;
|
|
|
|
+
|
|
|
|
+ err = der_decode_sequence_multi(in, inlen, LTC_ASN1_SHORT_INTEGER, 1UL, &version,
|
|
|
|
+ LTC_ASN1_EOL, 0UL, NULL);
|
|
|
|
+
|
|
|
|
+ if (err == CRYPT_OVERFLOW) {
|
|
|
|
+ /* the version would fit into an LTC_ASN1_SHORT_INTEGER
|
|
|
|
+ * so we try to decode as a public key
|
|
|
|
+ */
|
|
|
|
+ if ((err = der_decode_sequence_multi(in, inlen,
|
|
|
|
+ LTC_ASN1_INTEGER, 1UL, key->N,
|
|
|
|
+ LTC_ASN1_INTEGER, 1UL, key->e,
|
|
|
|
+ LTC_ASN1_EOL, 0UL, NULL)) == CRYPT_OK) {
|
|
|
|
+ key->type = PK_PUBLIC;
|
|
|
|
+ }
|
|
|
|
+ goto LBL_OUT;
|
|
|
|
+ } else if (err != CRYPT_INPUT_TOO_LONG) {
|
|
|
|
+ /* couldn't decode the version, so error out */
|
|
|
|
+ goto LBL_OUT;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (version == 0) {
|
|
|
|
+ /* it's a private key */
|
|
|
|
+ if ((err = der_decode_sequence_multi(in, inlen,
|
|
|
|
+ LTC_ASN1_SHORT_INTEGER, 1UL, &version,
|
|
|
|
+ LTC_ASN1_INTEGER, 1UL, key->N,
|
|
|
|
+ LTC_ASN1_INTEGER, 1UL, key->e,
|
|
|
|
+ LTC_ASN1_INTEGER, 1UL, key->d,
|
|
|
|
+ LTC_ASN1_INTEGER, 1UL, key->p,
|
|
|
|
+ LTC_ASN1_INTEGER, 1UL, key->q,
|
|
|
|
+ LTC_ASN1_INTEGER, 1UL, key->dP,
|
|
|
|
+ LTC_ASN1_INTEGER, 1UL, key->dQ,
|
|
|
|
+ LTC_ASN1_INTEGER, 1UL, key->qP,
|
|
|
|
+ LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
|
|
|
|
+ goto LBL_OUT;
|
|
|
|
+ }
|
|
|
|
+ key->type = PK_PRIVATE;
|
|
|
|
+ } else if (version == 1) {
|
|
|
|
+ /* we don't support multi-prime RSA */
|
|
|
|
+ err = CRYPT_PK_INVALID_TYPE;
|
|
|
|
+ goto LBL_OUT;
|
|
|
|
+ }
|
|
|
|
+ err = CRYPT_OK;
|
|
|
|
+LBL_OUT:
|
|
|
|
+ return err;
|
|
|
|
+}
|
|
|
|
+
|
|
/**
|
|
/**
|
|
- Import an RSAPublicKey or RSAPrivateKey [two-prime only, only support >= 1024-bit keys, defined in PKCS #1 v2.1]
|
|
|
|
|
|
+ Import multiple formats of RSA public and private keys.
|
|
|
|
+
|
|
|
|
+ RSAPublicKey or RSAPrivateKey as defined in PKCS #1 v2.1 [two-prime only]
|
|
|
|
+ SubjectPublicKeyInfo formatted public keys
|
|
|
|
+
|
|
@param in The packet to import from
|
|
@param in The packet to import from
|
|
@param inlen It's length (octets)
|
|
@param inlen It's length (octets)
|
|
@param key [out] Destination for newly imported key
|
|
@param key [out] Destination for newly imported key
|
|
@@ -19,7 +85,6 @@
|
|
int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
|
|
int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
|
|
{
|
|
{
|
|
int err;
|
|
int err;
|
|
- void *zero;
|
|
|
|
unsigned char *tmpbuf=NULL;
|
|
unsigned char *tmpbuf=NULL;
|
|
unsigned long tmpbuf_len, len;
|
|
unsigned long tmpbuf_len, len;
|
|
|
|
|
|
@@ -60,50 +125,9 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
|
|
}
|
|
}
|
|
|
|
|
|
/* not SSL public key, try to match against PKCS #1 standards */
|
|
/* not SSL public key, try to match against PKCS #1 standards */
|
|
- err = der_decode_sequence_multi(in, inlen, LTC_ASN1_INTEGER, 1UL, key->N,
|
|
|
|
- LTC_ASN1_EOL, 0UL, NULL);
|
|
|
|
-
|
|
|
|
- if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) {
|
|
|
|
- goto LBL_ERR;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (mp_cmp_d(key->N, 0) == LTC_MP_EQ) {
|
|
|
|
- if ((err = mp_init(&zero)) != CRYPT_OK) {
|
|
|
|
- goto LBL_ERR;
|
|
|
|
- }
|
|
|
|
- /* it's a private key */
|
|
|
|
- if ((err = der_decode_sequence_multi(in, inlen,
|
|
|
|
- LTC_ASN1_INTEGER, 1UL, zero,
|
|
|
|
- LTC_ASN1_INTEGER, 1UL, key->N,
|
|
|
|
- LTC_ASN1_INTEGER, 1UL, key->e,
|
|
|
|
- LTC_ASN1_INTEGER, 1UL, key->d,
|
|
|
|
- LTC_ASN1_INTEGER, 1UL, key->p,
|
|
|
|
- LTC_ASN1_INTEGER, 1UL, key->q,
|
|
|
|
- LTC_ASN1_INTEGER, 1UL, key->dP,
|
|
|
|
- LTC_ASN1_INTEGER, 1UL, key->dQ,
|
|
|
|
- LTC_ASN1_INTEGER, 1UL, key->qP,
|
|
|
|
- LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
|
|
|
|
- mp_clear(zero);
|
|
|
|
- goto LBL_ERR;
|
|
|
|
- }
|
|
|
|
- mp_clear(zero);
|
|
|
|
- key->type = PK_PRIVATE;
|
|
|
|
- } else if (mp_cmp_d(key->N, 1) == LTC_MP_EQ) {
|
|
|
|
- /* we don't support multi-prime RSA */
|
|
|
|
- err = CRYPT_PK_INVALID_TYPE;
|
|
|
|
- goto LBL_ERR;
|
|
|
|
- } else {
|
|
|
|
- /* it's a public key and we lack e */
|
|
|
|
- if ((err = der_decode_sequence_multi(in, inlen,
|
|
|
|
- LTC_ASN1_INTEGER, 1UL, key->N,
|
|
|
|
- LTC_ASN1_INTEGER, 1UL, key->e,
|
|
|
|
- LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
|
|
|
|
- goto LBL_ERR;
|
|
|
|
- }
|
|
|
|
- key->type = PK_PUBLIC;
|
|
|
|
|
|
+ if ((err = rsa_import_pkcs1(in, inlen, key)) == CRYPT_OK) {
|
|
|
|
+ goto LBL_FREE;
|
|
}
|
|
}
|
|
- err = CRYPT_OK;
|
|
|
|
- goto LBL_FREE;
|
|
|
|
|
|
|
|
LBL_ERR:
|
|
LBL_ERR:
|
|
rsa_free(key);
|
|
rsa_free(key);
|