Merge tag 'pull-loongarch-20241016' of https://gitlab.com/gaosong/qemu into staging
[qemu/armbru.git] / crypto / rsakey-nettle.c.inc
blobb7f34b02345a63ab64fbb234789cded4bc47bd9a
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  */
22 #include <nettle/asn1.h>
24 #include "qemu/osdep.h"
25 #include "qapi/error.h"
26 #include "rsakey.h"
28 static bool DumpMPI(struct asn1_der_iterator *i, QCryptoAkCipherMPI *mpi)
30     mpi->data = g_memdup2(i->data, i->length);
31     mpi->len = i->length;
32     return true;
35 static bool GetMPI(struct asn1_der_iterator *i, QCryptoAkCipherMPI *mpi)
37     if (asn1_der_iterator_next(i) != ASN1_ITERATOR_PRIMITIVE ||
38         i->type != ASN1_INTEGER) {
39         return false;
40     }
41     return DumpMPI(i, mpi);
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  */
58 static QCryptoAkCipherRSAKey *qcrypto_nettle_rsa_private_key_parse(
59     const uint8_t *key, size_t keylen, Error **errp)
61     QCryptoAkCipherRSAKey *rsa = g_new0(QCryptoAkCipherRSAKey, 1);
62     struct asn1_der_iterator i;
63     uint32_t version;
64     int tag;
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     }
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     }
101     if (asn1_der_iterator_next(&i) != ASN1_ITERATOR_END) {
102         goto error;
103     }
105     return rsa;
107 error:
108     error_setg(errp, "Failed to parse RSA private key");
109     qcrypto_akcipher_rsakey_free(rsa);
110     return NULL;
114  *        RsaPubKey ::= SEQUENCE {
115  *             n           INTEGER
116  *             e           INTEGER
117  *         }
118  */
119 static QCryptoAkCipherRSAKey *qcrypto_nettle_rsa_public_key_parse(
120     const uint8_t *key, size_t keylen, Error **errp)
123     QCryptoAkCipherRSAKey *rsa = g_new0(QCryptoAkCipherRSAKey, 1);
124     struct asn1_der_iterator i;
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     }
135     return rsa;
137 error:
138     error_setg(errp, "Failed to parse RSA public key");
139     qcrypto_akcipher_rsakey_free(rsa);
140     return NULL;
143 QCryptoAkCipherRSAKey *qcrypto_akcipher_rsakey_parse(
144     QCryptoAkCipherKeyType type, const uint8_t *key,
145     size_t keylen, Error **errp)
147     switch (type) {
148     case QCRYPTO_AK_CIPHER_KEY_TYPE_PRIVATE:
149         return qcrypto_nettle_rsa_private_key_parse(key, keylen, errp);
151     case QCRYPTO_AK_CIPHER_KEY_TYPE_PUBLIC:
152         return qcrypto_nettle_rsa_public_key_parse(key, keylen, errp);
154     default:
155         error_setg(errp, "Unknown key type: %d", type);
156         return NULL;
157     }