AuroraRuntime/Source/Extensions/LTC/LTCImportEx.c
2021-06-27 22:25:29 +01:00

159 lines
4.0 KiB
C

/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: LTCImportEx.c
Date: 2021-6-24
Author: Reece
***/
#include <tomcrypt.h>
#include "tomcrypt_private.h"
#include "LTCExtensions.h"
int rsa_import_ex(const unsigned char *in, unsigned long inlen, rsa_key *key, int flags)
{
int err;
void *zero;
char scratch[4096];
const unsigned char *rsa = scratch;
unsigned long rsa_len = sizeof(scratch);
unsigned long len;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(key != NULL);
LTC_ARGCHK(ltc_mp.name != NULL);
/* init key */
if ((err = rsa_init(key)) != CRYPT_OK)
{
return err;
}
len = 0;
if ((flags & kRsaFlagPKCS1) != 0)
{
rsa = in;
rsa_len = inlen;
}
else
{
unsigned long oid[16];
const char *rsaoid;
ltc_asn1_list alg_seq[2], top_seq[3];
ltc_asn1_list *l = NULL;
/* get RSA alg oid */
err = pk_get_oid(PKA_RSA, &rsaoid);
if (err != CRYPT_OK)
{
goto LBL_ERR;
}
if ((err = mp_init(&zero)) != CRYPT_OK)
{
goto LBL_ERR;
}
LTC_SET_ASN1(alg_seq, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, 16UL);
LTC_SET_ASN1(alg_seq, 1, LTC_ASN1_NULL, NULL, 0UL);// << key
if ((flags & kRsaFlagPublic) == 0)
{
LTC_SET_ASN1(top_seq, 0, LTC_ASN1_INTEGER, zero, 1UL);
LTC_SET_ASN1(top_seq, 1, LTC_ASN1_SEQUENCE, alg_seq, 2UL);
LTC_SET_ASN1(top_seq, 2, LTC_ASN1_OCTET_STRING, rsa, rsa_len);
err = der_decode_sequence(in, inlen, top_seq, 3UL);
}
else
{
LTC_SET_ASN1(top_seq, 0, LTC_ASN1_SEQUENCE, alg_seq, 1UL);
LTC_SET_ASN1(top_seq, 1, LTC_ASN1_BIT_STRING, rsa, rsa_len);
err = der_decode_sequence(in, inlen, top_seq, 2UL);
}
mp_clear(zero);
rsa_len = top_seq[2].size;
if (err != CRYPT_OK)
{
goto LBL_ERR;
}
/* check alg oid */
if ((err = pk_oid_cmp_with_asn1(rsaoid, &alg_seq[0])) != CRYPT_OK)
{
goto LBL_ERR;
}
}
if ((flags & kRsaFlagPublic) != 0)
{
/* it's a public key and we lack e */
if ((err = der_decode_sequence_multi(rsa, rsa_len,
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;
}
else
{
err = der_decode_sequence_multi(rsa, rsa_len, 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(rsa, rsa_len,
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
{
err = CRYPT_PK_INVALID_TYPE;
goto LBL_ERR;
}
}
return CRYPT_OK;
LBL_ERR:
rsa_free(key);
return err;
}