xref: /openbmc/qemu/crypto/rsakey-nettle.c.inc (revision df22fbb7)
1/*
2 * QEMU Crypto akcipher algorithms
3 *
4 * Copyright (c) 2022 Bytedance
5 * Author: lei he <helei.sig11@bytedance.com>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22#include <nettle/asn1.h>
23
24#include "qemu/osdep.h"
25#include "qapi/error.h"
26#include "rsakey.h"
27
28static bool DumpMPI(struct asn1_der_iterator *i, QCryptoAkCipherMPI *mpi)
29{
30    mpi->data = g_memdup2(i->data, i->length);
31    mpi->len = i->length;
32    return true;
33}
34
35static bool GetMPI(struct asn1_der_iterator *i, QCryptoAkCipherMPI *mpi)
36{
37    if (asn1_der_iterator_next(i) != ASN1_ITERATOR_PRIMITIVE ||
38        i->type != ASN1_INTEGER) {
39        return false;
40    }
41    return DumpMPI(i, mpi);
42}
43
44/**
45 *        RsaPrivKey ::= SEQUENCE {
46 *             version     INTEGER
47 *             n           INTEGER
48 *             e           INTEGER
49 *             d           INTEGER
50 *             p           INTEGER
51 *             q           INTEGER
52 *             dp          INTEGER
53 *             dq          INTEGER
54 *             u           INTEGER
55 *       otherPrimeInfos   OtherPrimeInfos OPTIONAL
56 *         }
57 */
58static QCryptoAkCipherRSAKey *qcrypto_nettle_rsa_private_key_parse(
59    const uint8_t *key, size_t keylen, Error **errp)
60{
61    QCryptoAkCipherRSAKey *rsa = g_new0(QCryptoAkCipherRSAKey, 1);
62    struct asn1_der_iterator i;
63    uint32_t version;
64    int tag;
65
66    /* Parse entire struct */
67    if (asn1_der_iterator_first(&i, keylen, key) != ASN1_ITERATOR_CONSTRUCTED ||
68        i.type != ASN1_SEQUENCE ||
69        asn1_der_decode_constructed_last(&i) != ASN1_ITERATOR_PRIMITIVE ||
70        i.type != ASN1_INTEGER ||
71        !asn1_der_get_uint32(&i, &version) ||
72        version > 1 ||
73        !GetMPI(&i, &rsa->n) ||
74        !GetMPI(&i, &rsa->e) ||
75        !GetMPI(&i, &rsa->d) ||
76        !GetMPI(&i, &rsa->p) ||
77        !GetMPI(&i, &rsa->q) ||
78        !GetMPI(&i, &rsa->dp) ||
79        !GetMPI(&i, &rsa->dq) ||
80        !GetMPI(&i, &rsa->u)) {
81        goto error;
82    }
83
84    if (version == 1) {
85        tag = asn1_der_iterator_next(&i);
86        /**
87         * According to the standard otherPrimeInfos must be present for
88         * version 1. There is no strict verification here, this is to be
89         * compatible with the unit test of the kernel. TODO: remove this
90         * until linux-kernel's unit-test is fixed;
91         */
92        if (tag == ASN1_ITERATOR_END) {
93            return rsa;
94        }
95        if (tag != ASN1_ITERATOR_CONSTRUCTED ||
96            i.type != ASN1_SEQUENCE) {
97            goto error;
98        }
99    }
100
101    if (asn1_der_iterator_next(&i) != ASN1_ITERATOR_END) {
102        goto error;
103    }
104
105    return rsa;
106
107error:
108    error_setg(errp, "Failed to parse RSA private key");
109    qcrypto_akcipher_rsakey_free(rsa);
110    return NULL;
111}
112
113/**
114 *        RsaPubKey ::= SEQUENCE {
115 *             n           INTEGER
116 *             e           INTEGER
117 *         }
118 */
119static QCryptoAkCipherRSAKey *qcrypto_nettle_rsa_public_key_parse(
120    const uint8_t *key, size_t keylen, Error **errp)
121{
122
123    QCryptoAkCipherRSAKey *rsa = g_new0(QCryptoAkCipherRSAKey, 1);
124    struct asn1_der_iterator i;
125
126    if (asn1_der_iterator_first(&i, keylen, key) != ASN1_ITERATOR_CONSTRUCTED ||
127        i.type != ASN1_SEQUENCE ||
128        asn1_der_decode_constructed_last(&i) != ASN1_ITERATOR_PRIMITIVE ||
129        !DumpMPI(&i, &rsa->n) ||
130        !GetMPI(&i, &rsa->e) ||
131        asn1_der_iterator_next(&i) != ASN1_ITERATOR_END) {
132        goto error;
133    }
134
135    return rsa;
136
137error:
138    error_setg(errp, "Failed to parse RSA public key");
139    qcrypto_akcipher_rsakey_free(rsa);
140    return NULL;
141}
142
143QCryptoAkCipherRSAKey *qcrypto_akcipher_rsakey_parse(
144    QCryptoAkCipherKeyType type, const uint8_t *key,
145    size_t keylen, Error **errp)
146{
147    switch (type) {
148    case QCRYPTO_AKCIPHER_KEY_TYPE_PRIVATE:
149        return qcrypto_nettle_rsa_private_key_parse(key, keylen, errp);
150
151    case QCRYPTO_AKCIPHER_KEY_TYPE_PUBLIC:
152        return qcrypto_nettle_rsa_public_key_parse(key, keylen, errp);
153
154    default:
155        error_setg(errp, "Unknown key type: %d", type);
156        return NULL;
157    }
158}
159