xref: /openbmc/qemu/crypto/rsakey-nettle.c.inc (revision b8eada54b2ad8a7d98d93d5ab4d3e888c5880097)
14c5e512eSLei He/*
24c5e512eSLei He * QEMU Crypto akcipher algorithms
34c5e512eSLei He *
44c5e512eSLei He * Copyright (c) 2022 Bytedance
54c5e512eSLei He * Author: lei he <helei.sig11@bytedance.com>
64c5e512eSLei He *
74c5e512eSLei He * This library is free software; you can redistribute it and/or
84c5e512eSLei He * modify it under the terms of the GNU Lesser General Public
94c5e512eSLei He * License as published by the Free Software Foundation; either
104c5e512eSLei He * version 2.1 of the License, or (at your option) any later version.
114c5e512eSLei He *
124c5e512eSLei He * This library is distributed in the hope that it will be useful,
134c5e512eSLei He * but WITHOUT ANY WARRANTY; without even the implied warranty of
144c5e512eSLei He * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
154c5e512eSLei He * Lesser General Public License for more details.
164c5e512eSLei He *
174c5e512eSLei He * You should have received a copy of the GNU Lesser General Public
184c5e512eSLei He * License along with this library; if not, see <http://www.gnu.org/licenses/>.
194c5e512eSLei He *
204c5e512eSLei He */
214c5e512eSLei He
224c5e512eSLei He#include <nettle/asn1.h>
234c5e512eSLei He
244c5e512eSLei He#include "qemu/osdep.h"
254c5e512eSLei He#include "qapi/error.h"
264c5e512eSLei He#include "rsakey.h"
274c5e512eSLei He
284c5e512eSLei Hestatic bool DumpMPI(struct asn1_der_iterator *i, QCryptoAkCipherMPI *mpi)
294c5e512eSLei He{
304c5e512eSLei He    mpi->data = g_memdup2(i->data, i->length);
314c5e512eSLei He    mpi->len = i->length;
324c5e512eSLei He    return true;
334c5e512eSLei He}
344c5e512eSLei He
354c5e512eSLei Hestatic bool GetMPI(struct asn1_der_iterator *i, QCryptoAkCipherMPI *mpi)
364c5e512eSLei He{
374c5e512eSLei He    if (asn1_der_iterator_next(i) != ASN1_ITERATOR_PRIMITIVE ||
384c5e512eSLei He        i->type != ASN1_INTEGER) {
394c5e512eSLei He        return false;
404c5e512eSLei He    }
414c5e512eSLei He    return DumpMPI(i, mpi);
424c5e512eSLei He}
434c5e512eSLei He
444c5e512eSLei He/**
454c5e512eSLei He *        RsaPrivKey ::= SEQUENCE {
464c5e512eSLei He *             version     INTEGER
474c5e512eSLei He *             n           INTEGER
484c5e512eSLei He *             e           INTEGER
494c5e512eSLei He *             d           INTEGER
504c5e512eSLei He *             p           INTEGER
514c5e512eSLei He *             q           INTEGER
524c5e512eSLei He *             dp          INTEGER
534c5e512eSLei He *             dq          INTEGER
544c5e512eSLei He *             u           INTEGER
554c5e512eSLei He *       otherPrimeInfos   OtherPrimeInfos OPTIONAL
564c5e512eSLei He *         }
574c5e512eSLei He */
584c5e512eSLei Hestatic QCryptoAkCipherRSAKey *qcrypto_nettle_rsa_private_key_parse(
594c5e512eSLei He    const uint8_t *key, size_t keylen, Error **errp)
604c5e512eSLei He{
614c5e512eSLei He    QCryptoAkCipherRSAKey *rsa = g_new0(QCryptoAkCipherRSAKey, 1);
624c5e512eSLei He    struct asn1_der_iterator i;
634c5e512eSLei He    uint32_t version;
644c5e512eSLei He    int tag;
654c5e512eSLei He
664c5e512eSLei He    /* Parse entire struct */
674c5e512eSLei He    if (asn1_der_iterator_first(&i, keylen, key) != ASN1_ITERATOR_CONSTRUCTED ||
684c5e512eSLei He        i.type != ASN1_SEQUENCE ||
694c5e512eSLei He        asn1_der_decode_constructed_last(&i) != ASN1_ITERATOR_PRIMITIVE ||
704c5e512eSLei He        i.type != ASN1_INTEGER ||
714c5e512eSLei He        !asn1_der_get_uint32(&i, &version) ||
724c5e512eSLei He        version > 1 ||
734c5e512eSLei He        !GetMPI(&i, &rsa->n) ||
744c5e512eSLei He        !GetMPI(&i, &rsa->e) ||
754c5e512eSLei He        !GetMPI(&i, &rsa->d) ||
764c5e512eSLei He        !GetMPI(&i, &rsa->p) ||
774c5e512eSLei He        !GetMPI(&i, &rsa->q) ||
784c5e512eSLei He        !GetMPI(&i, &rsa->dp) ||
794c5e512eSLei He        !GetMPI(&i, &rsa->dq) ||
804c5e512eSLei He        !GetMPI(&i, &rsa->u)) {
814c5e512eSLei He        goto error;
824c5e512eSLei He    }
834c5e512eSLei He
844c5e512eSLei He    if (version == 1) {
854c5e512eSLei He        tag = asn1_der_iterator_next(&i);
864c5e512eSLei He        /**
874c5e512eSLei He         * According to the standard otherPrimeInfos must be present for
884c5e512eSLei He         * version 1. There is no strict verification here, this is to be
894c5e512eSLei He         * compatible with the unit test of the kernel. TODO: remove this
904c5e512eSLei He         * until linux-kernel's unit-test is fixed;
914c5e512eSLei He         */
924c5e512eSLei He        if (tag == ASN1_ITERATOR_END) {
934c5e512eSLei He            return rsa;
944c5e512eSLei He        }
954c5e512eSLei He        if (tag != ASN1_ITERATOR_CONSTRUCTED ||
964c5e512eSLei He            i.type != ASN1_SEQUENCE) {
974c5e512eSLei He            goto error;
984c5e512eSLei He        }
994c5e512eSLei He    }
1004c5e512eSLei He
1014c5e512eSLei He    if (asn1_der_iterator_next(&i) != ASN1_ITERATOR_END) {
1024c5e512eSLei He        goto error;
1034c5e512eSLei He    }
1044c5e512eSLei He
1054c5e512eSLei He    return rsa;
1064c5e512eSLei He
1074c5e512eSLei Heerror:
1084c5e512eSLei He    error_setg(errp, "Failed to parse RSA private key");
1094c5e512eSLei He    qcrypto_akcipher_rsakey_free(rsa);
1104c5e512eSLei He    return NULL;
1114c5e512eSLei He}
1124c5e512eSLei He
1134c5e512eSLei He/**
1144c5e512eSLei He *        RsaPubKey ::= SEQUENCE {
1154c5e512eSLei He *             n           INTEGER
1164c5e512eSLei He *             e           INTEGER
1174c5e512eSLei He *         }
1184c5e512eSLei He */
1194c5e512eSLei Hestatic QCryptoAkCipherRSAKey *qcrypto_nettle_rsa_public_key_parse(
1204c5e512eSLei He    const uint8_t *key, size_t keylen, Error **errp)
1214c5e512eSLei He{
1224c5e512eSLei He
1234c5e512eSLei He    QCryptoAkCipherRSAKey *rsa = g_new0(QCryptoAkCipherRSAKey, 1);
1244c5e512eSLei He    struct asn1_der_iterator i;
1254c5e512eSLei He
1264c5e512eSLei He    if (asn1_der_iterator_first(&i, keylen, key) != ASN1_ITERATOR_CONSTRUCTED ||
1274c5e512eSLei He        i.type != ASN1_SEQUENCE ||
1284c5e512eSLei He        asn1_der_decode_constructed_last(&i) != ASN1_ITERATOR_PRIMITIVE ||
1294c5e512eSLei He        !DumpMPI(&i, &rsa->n) ||
1304c5e512eSLei He        !GetMPI(&i, &rsa->e) ||
1314c5e512eSLei He        asn1_der_iterator_next(&i) != ASN1_ITERATOR_END) {
1324c5e512eSLei He        goto error;
1334c5e512eSLei He    }
1344c5e512eSLei He
1354c5e512eSLei He    return rsa;
1364c5e512eSLei He
1374c5e512eSLei Heerror:
1384c5e512eSLei He    error_setg(errp, "Failed to parse RSA public key");
1394c5e512eSLei He    qcrypto_akcipher_rsakey_free(rsa);
1404c5e512eSLei He    return NULL;
1414c5e512eSLei He}
1424c5e512eSLei He
1434c5e512eSLei HeQCryptoAkCipherRSAKey *qcrypto_akcipher_rsakey_parse(
1444c5e512eSLei He    QCryptoAkCipherKeyType type, const uint8_t *key,
1454c5e512eSLei He    size_t keylen, Error **errp)
1464c5e512eSLei He{
1474c5e512eSLei He    switch (type) {
148*5f4059efSMarkus Armbruster    case QCRYPTO_AK_CIPHER_KEY_TYPE_PRIVATE:
1494c5e512eSLei He        return qcrypto_nettle_rsa_private_key_parse(key, keylen, errp);
1504c5e512eSLei He
151*5f4059efSMarkus Armbruster    case QCRYPTO_AK_CIPHER_KEY_TYPE_PUBLIC:
1524c5e512eSLei He        return qcrypto_nettle_rsa_public_key_parse(key, keylen, errp);
1534c5e512eSLei He
1544c5e512eSLei He    default:
1554c5e512eSLei He        error_setg(errp, "Unknown key type: %d", type);
1564c5e512eSLei He        return NULL;
1574c5e512eSLei He    }
1584c5e512eSLei He}
159