/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: LTCExport.c Date: 2021-6-24 Author: Reece ***/ #include "tomcrypt_private.h" #include "LTCExtensions.h" int rsa_basic_export(unsigned char *out, unsigned long *outlen, const rsa_key *key, int flags) { unsigned long zero = 0; LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); if ((flags & kRsaFlagPublic) == 0) { if (key->type == PK_PUBLIC) { return CRYPT_INVALID_ARG; } /* private key */ /* output is Version, n, e, d, p, q, d mod (p-1), d mod (q - 1), 1/q mod p */ return der_encode_sequence_multi(out, outlen, LTC_ASN1_SHORT_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); } else { /* public key */ return der_encode_sequence_multi(out, outlen, LTC_ASN1_INTEGER, 1UL, key->N, LTC_ASN1_INTEGER, 1UL, key->e, LTC_ASN1_EOL, 0UL, NULL); } } int rsa_pkcs8_export(unsigned char *out, unsigned long *outlen, const rsa_key * key, int flags) { int ret; char temp[4096]; unsigned long length = sizeof(temp); if ((ret = rsa_basic_export(temp, &length, key, flags)) != CRYPT_OK) { return ret; } if ((flags & kRsaFlagPKCS1) != 0) { *outlen = length; if (*outlen < length) { return CRYPT_BUFFER_OVERFLOW; } memcpy(out, temp, length); return CRYPT_OK; } else { unsigned long oid[16]; const char *oidReference; ret = pk_get_oid(PKA_RSA, &oidReference); if (ret != CRYPT_OK) { return ret; } unsigned long oidArraySize = 16; ret = pk_oid_str_to_num(oidReference, oid, &oidArraySize); if (ret != CRYPT_OK) { return ret; } if ((flags & kRsaFlagPublic) == 0) { if (key->type == PK_PUBLIC) { return CRYPT_INVALID_ARG; } ltc_asn1_list alg_seq[2], top_seq[3]; unsigned long zero = 0; LTC_SET_ASN1(alg_seq, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, oidArraySize); LTC_SET_ASN1(alg_seq, 1, LTC_ASN1_NULL, NULL, 0UL); LTC_SET_ASN1(top_seq, 0, LTC_ASN1_SHORT_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, temp, length); ret = der_encode_sequence(top_seq, 3, out, outlen); } else { ltc_asn1_list alg_seq[2]; LTC_SET_ASN1(alg_seq, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, oidArraySize); // TODO: return false? ret = der_encode_sequence_multi(out, outlen, LTC_ASN1_SEQUENCE, 1, alg_seq, LTC_ASN1_BIT_STRING, length, temp, LTC_ASN1_EOL, 0UL, NULL); } return ret; } }