xref: /openbmc/qemu/crypto/rsakey-builtin.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 "der.h"
234c5e512eSLei He#include "rsakey.h"
244c5e512eSLei He
254c5e512eSLei Hestatic int extract_mpi(void *ctx, const uint8_t *value,
264c5e512eSLei He                       size_t vlen, Error **errp)
274c5e512eSLei He{
284c5e512eSLei He    QCryptoAkCipherMPI *mpi = (QCryptoAkCipherMPI *)ctx;
294c5e512eSLei He    if (vlen == 0) {
304c5e512eSLei He        error_setg(errp, "Empty mpi field");
314c5e512eSLei He        return -1;
324c5e512eSLei He    }
334c5e512eSLei He    mpi->data = g_memdup2(value, vlen);
344c5e512eSLei He    mpi->len = vlen;
354c5e512eSLei He    return 0;
364c5e512eSLei He}
374c5e512eSLei He
384c5e512eSLei Hestatic int extract_version(void *ctx, const uint8_t *value,
394c5e512eSLei He                           size_t vlen, Error **errp)
404c5e512eSLei He{
414c5e512eSLei He    uint8_t *version = (uint8_t *)ctx;
424c5e512eSLei He    if (vlen != 1 || *value > 1) {
434c5e512eSLei He        error_setg(errp, "Invalid rsakey version");
444c5e512eSLei He        return -1;
454c5e512eSLei He    }
464c5e512eSLei He    *version = *value;
474c5e512eSLei He    return 0;
484c5e512eSLei He}
494c5e512eSLei He
504c5e512eSLei Hestatic int extract_seq_content(void *ctx, const uint8_t *value,
514c5e512eSLei He                               size_t vlen, Error **errp)
524c5e512eSLei He{
534c5e512eSLei He    const uint8_t **content = (const uint8_t **)ctx;
544c5e512eSLei He    if (vlen == 0) {
554c5e512eSLei He        error_setg(errp, "Empty sequence");
564c5e512eSLei He        return -1;
574c5e512eSLei He    }
584c5e512eSLei He    *content = value;
594c5e512eSLei He    return 0;
604c5e512eSLei He}
614c5e512eSLei He
624c5e512eSLei He/**
634c5e512eSLei He *
644c5e512eSLei He *        RsaPubKey ::= SEQUENCE {
654c5e512eSLei He *             n           INTEGER
664c5e512eSLei He *             e           INTEGER
674c5e512eSLei He *         }
684c5e512eSLei He */
694c5e512eSLei Hestatic QCryptoAkCipherRSAKey *qcrypto_builtin_rsa_public_key_parse(
704c5e512eSLei He    const uint8_t *key, size_t keylen, Error **errp)
714c5e512eSLei He{
724c5e512eSLei He    QCryptoAkCipherRSAKey *rsa = g_new0(QCryptoAkCipherRSAKey, 1);
734c5e512eSLei He    const uint8_t *seq;
744c5e512eSLei He    size_t seq_length;
754c5e512eSLei He    int decode_ret;
764c5e512eSLei He
774c5e512eSLei He    decode_ret = qcrypto_der_decode_seq(&key, &keylen,
784c5e512eSLei He                                        extract_seq_content, &seq, errp);
794c5e512eSLei He    if (decode_ret < 0 || keylen != 0) {
804c5e512eSLei He        goto error;
814c5e512eSLei He    }
824c5e512eSLei He    seq_length = decode_ret;
834c5e512eSLei He
844c5e512eSLei He    if (qcrypto_der_decode_int(&seq, &seq_length, extract_mpi,
854c5e512eSLei He                               &rsa->n, errp) < 0 ||
864c5e512eSLei He        qcrypto_der_decode_int(&seq, &seq_length, extract_mpi,
874c5e512eSLei He                               &rsa->e, errp) < 0) {
884c5e512eSLei He        goto error;
894c5e512eSLei He    }
904c5e512eSLei He    if (seq_length != 0) {
91e158f8e9SMarkus Armbruster        error_setg(errp, "Invalid RSA public key");
924c5e512eSLei He        goto error;
934c5e512eSLei He    }
944c5e512eSLei He
954c5e512eSLei He    return rsa;
964c5e512eSLei He
974c5e512eSLei Heerror:
984c5e512eSLei He    qcrypto_akcipher_rsakey_free(rsa);
994c5e512eSLei He    return NULL;
1004c5e512eSLei He}
1014c5e512eSLei He
1024c5e512eSLei He/**
1034c5e512eSLei He *        RsaPrivKey ::= SEQUENCE {
1044c5e512eSLei He *             version     INTEGER
1054c5e512eSLei He *             n           INTEGER
1064c5e512eSLei He *             e           INTEGER
1074c5e512eSLei He *             d           INTEGER
1084c5e512eSLei He *             p           INTEGER
1094c5e512eSLei He *             q           INTEGER
1104c5e512eSLei He *             dp          INTEGER
1114c5e512eSLei He *             dq          INTEGER
1124c5e512eSLei He *             u           INTEGER
1134c5e512eSLei He *       otherPrimeInfos   OtherPrimeInfos OPTIONAL
1144c5e512eSLei He *         }
1154c5e512eSLei He */
1164c5e512eSLei Hestatic QCryptoAkCipherRSAKey *qcrypto_builtin_rsa_private_key_parse(
1174c5e512eSLei He    const uint8_t *key, size_t keylen, Error **errp)
1184c5e512eSLei He{
1194c5e512eSLei He    QCryptoAkCipherRSAKey *rsa = g_new0(QCryptoAkCipherRSAKey, 1);
1204c5e512eSLei He    uint8_t version;
1214c5e512eSLei He    const uint8_t *seq;
1224c5e512eSLei He    int decode_ret;
1234c5e512eSLei He    size_t seq_length;
1244c5e512eSLei He
1254c5e512eSLei He    decode_ret = qcrypto_der_decode_seq(&key, &keylen, extract_seq_content,
1264c5e512eSLei He                                        &seq, errp);
1274c5e512eSLei He    if (decode_ret < 0 || keylen != 0) {
1284c5e512eSLei He        goto error;
1294c5e512eSLei He    }
1304c5e512eSLei He    seq_length = decode_ret;
1314c5e512eSLei He
1324c5e512eSLei He    decode_ret = qcrypto_der_decode_int(&seq, &seq_length, extract_version,
1334c5e512eSLei He                                        &version, errp);
1344c5e512eSLei He
1354c5e512eSLei He    if (qcrypto_der_decode_int(&seq, &seq_length, extract_mpi,
1364c5e512eSLei He                               &rsa->n, errp) < 0 ||
1374c5e512eSLei He        qcrypto_der_decode_int(&seq, &seq_length, extract_mpi,
1384c5e512eSLei He                               &rsa->e, errp) < 0 ||
1394c5e512eSLei He        qcrypto_der_decode_int(&seq, &seq_length, extract_mpi,
1404c5e512eSLei He                               &rsa->d, errp) < 0 ||
1414c5e512eSLei He        qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, &rsa->p,
1424c5e512eSLei He                               errp) < 0 ||
1434c5e512eSLei He        qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, &rsa->q,
1444c5e512eSLei He                               errp) < 0 ||
1454c5e512eSLei He        qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, &rsa->dp,
1464c5e512eSLei He                               errp) < 0 ||
1474c5e512eSLei He        qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, &rsa->dq,
1484c5e512eSLei He                               errp) < 0 ||
1494c5e512eSLei He        qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, &rsa->u,
1504c5e512eSLei He                               errp) < 0) {
1514c5e512eSLei He        goto error;
1524c5e512eSLei He    }
1534c5e512eSLei He
1544c5e512eSLei He    /**
1554c5e512eSLei He     * According to the standard, otherPrimeInfos must be present for version 1.
1564c5e512eSLei He     * There is no strict verification here, this is to be compatible with
1574c5e512eSLei He     * the unit test of the kernel. TODO: remove this until linux kernel's
1584c5e512eSLei He     * unit-test is fixed.
1594c5e512eSLei He     */
1604c5e512eSLei He    if (version == 1 && seq_length != 0) {
1614c5e512eSLei He        if (qcrypto_der_decode_seq(&seq, &seq_length, NULL, NULL, errp) < 0) {
1624c5e512eSLei He            goto error;
1634c5e512eSLei He        }
1644c5e512eSLei He        if (seq_length != 0) {
1654c5e512eSLei He            goto error;
1664c5e512eSLei He        }
1674c5e512eSLei He        return rsa;
1684c5e512eSLei He    }
1694c5e512eSLei He    if (seq_length != 0) {
170e158f8e9SMarkus Armbruster        error_setg(errp, "Invalid RSA private key");
1714c5e512eSLei He        goto error;
1724c5e512eSLei He    }
1734c5e512eSLei He
1744c5e512eSLei He    return rsa;
1754c5e512eSLei He
1764c5e512eSLei Heerror:
1774c5e512eSLei He    qcrypto_akcipher_rsakey_free(rsa);
1784c5e512eSLei He    return NULL;
1794c5e512eSLei He}
1804c5e512eSLei He
1814c5e512eSLei HeQCryptoAkCipherRSAKey *qcrypto_akcipher_rsakey_parse(
1824c5e512eSLei He    QCryptoAkCipherKeyType type, const uint8_t *key,
1834c5e512eSLei He    size_t keylen, Error **errp)
1844c5e512eSLei He{
1854c5e512eSLei He    switch (type) {
186*5f4059efSMarkus Armbruster    case QCRYPTO_AK_CIPHER_KEY_TYPE_PRIVATE:
1874c5e512eSLei He        return qcrypto_builtin_rsa_private_key_parse(key, keylen, errp);
1884c5e512eSLei He
189*5f4059efSMarkus Armbruster    case QCRYPTO_AK_CIPHER_KEY_TYPE_PUBLIC:
1904c5e512eSLei He        return qcrypto_builtin_rsa_public_key_parse(key, keylen, errp);
1914c5e512eSLei He
1924c5e512eSLei He    default:
1934c5e512eSLei He        error_setg(errp, "Unknown key type: %d", type);
1944c5e512eSLei He        return NULL;
1954c5e512eSLei He    }
1964c5e512eSLei He}
197