|  | /* | 
|  | * QEMU Crypto akcipher algorithms | 
|  | * | 
|  | * Copyright (c) 2022 Bytedance | 
|  | * Author: lei he <helei.sig11@bytedance.com> | 
|  | * | 
|  | * 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 <http://www.gnu.org/licenses/>. | 
|  | * | 
|  | */ | 
|  |  | 
|  | #include <nettle/asn1.h> | 
|  |  | 
|  | #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; | 
|  | } | 
|  | } |