/* * QEMU Crypto akcipher algorithms * * Copyright (c) 2022 Bytedance * Author: lei he * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . * */ #include #include "qemu/osdep.h" #include "qapi/error.h" #include "rsakey.h" static bool DumpMPI(struct asn1_der_iterator *i, QCryptoAkCipherMPI *mpi) { mpi->data = g_memdup2(i->data, i->length); mpi->len = i->length; return true; } static bool GetMPI(struct asn1_der_iterator *i, QCryptoAkCipherMPI *mpi) { if (asn1_der_iterator_next(i) != ASN1_ITERATOR_PRIMITIVE || i->type != ASN1_INTEGER) { return false; } return DumpMPI(i, mpi); } /** * RsaPrivKey ::= SEQUENCE { * version INTEGER * n INTEGER * e INTEGER * d INTEGER * p INTEGER * q INTEGER * dp INTEGER * dq INTEGER * u INTEGER * otherPrimeInfos OtherPrimeInfos OPTIONAL * } */ static QCryptoAkCipherRSAKey *qcrypto_nettle_rsa_private_key_parse( const uint8_t *key, size_t keylen, Error **errp) { QCryptoAkCipherRSAKey *rsa = g_new0(QCryptoAkCipherRSAKey, 1); struct asn1_der_iterator i; uint32_t version; int tag; /* Parse entire struct */ if (asn1_der_iterator_first(&i, keylen, key) != ASN1_ITERATOR_CONSTRUCTED || i.type != ASN1_SEQUENCE || asn1_der_decode_constructed_last(&i) != ASN1_ITERATOR_PRIMITIVE || i.type != ASN1_INTEGER || !asn1_der_get_uint32(&i, &version) || version > 1 || !GetMPI(&i, &rsa->n) || !GetMPI(&i, &rsa->e) || !GetMPI(&i, &rsa->d) || !GetMPI(&i, &rsa->p) || !GetMPI(&i, &rsa->q) || !GetMPI(&i, &rsa->dp) || !GetMPI(&i, &rsa->dq) || !GetMPI(&i, &rsa->u)) { goto error; } if (version == 1) { tag = asn1_der_iterator_next(&i); /** * According to the standard otherPrimeInfos must be present for * version 1. There is no strict verification here, this is to be * compatible with the unit test of the kernel. TODO: remove this * until linux-kernel's unit-test is fixed; */ if (tag == ASN1_ITERATOR_END) { return rsa; } if (tag != ASN1_ITERATOR_CONSTRUCTED || i.type != ASN1_SEQUENCE) { goto error; } } if (asn1_der_iterator_next(&i) != ASN1_ITERATOR_END) { goto error; } return rsa; error: error_setg(errp, "Failed to parse RSA private key"); qcrypto_akcipher_rsakey_free(rsa); return NULL; } /** * RsaPubKey ::= SEQUENCE { * n INTEGER * e INTEGER * } */ static QCryptoAkCipherRSAKey *qcrypto_nettle_rsa_public_key_parse( const uint8_t *key, size_t keylen, Error **errp) { QCryptoAkCipherRSAKey *rsa = g_new0(QCryptoAkCipherRSAKey, 1); struct asn1_der_iterator i; if (asn1_der_iterator_first(&i, keylen, key) != ASN1_ITERATOR_CONSTRUCTED || i.type != ASN1_SEQUENCE || asn1_der_decode_constructed_last(&i) != ASN1_ITERATOR_PRIMITIVE || !DumpMPI(&i, &rsa->n) || !GetMPI(&i, &rsa->e) || asn1_der_iterator_next(&i) != ASN1_ITERATOR_END) { goto error; } return rsa; error: error_setg(errp, "Failed to parse RSA public key"); qcrypto_akcipher_rsakey_free(rsa); return NULL; } QCryptoAkCipherRSAKey *qcrypto_akcipher_rsakey_parse( QCryptoAkCipherKeyType type, const uint8_t *key, size_t keylen, Error **errp) { switch (type) { case QCRYPTO_AK_CIPHER_KEY_TYPE_PRIVATE: return qcrypto_nettle_rsa_private_key_parse(key, keylen, errp); case QCRYPTO_AK_CIPHER_KEY_TYPE_PUBLIC: return qcrypto_nettle_rsa_public_key_parse(key, keylen, errp); default: error_setg(errp, "Unknown key type: %d", type); return NULL; } }