Merge tag 'mips-20221108' of https://github.com/philmd/qemu into staging
[qemu/ar7.git] / crypto / rsakey-builtin.c.inc
blobaeeacc8f9bfa377bfa5c5cb79d66c7efa790f834
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 "der.h"
23 #include "rsakey.h"
25 static int extract_mpi(void *ctx, const uint8_t *value,
26                        size_t vlen, Error **errp)
28     QCryptoAkCipherMPI *mpi = (QCryptoAkCipherMPI *)ctx;
29     if (vlen == 0) {
30         error_setg(errp, "Empty mpi field");
31         return -1;
32     }
33     mpi->data = g_memdup2(value, vlen);
34     mpi->len = vlen;
35     return 0;
38 static int extract_version(void *ctx, const uint8_t *value,
39                            size_t vlen, Error **errp)
41     uint8_t *version = (uint8_t *)ctx;
42     if (vlen != 1 || *value > 1) {
43         error_setg(errp, "Invalid rsakey version");
44         return -1;
45     }
46     *version = *value;
47     return 0;
50 static int extract_seq_content(void *ctx, const uint8_t *value,
51                                size_t vlen, Error **errp)
53     const uint8_t **content = (const uint8_t **)ctx;
54     if (vlen == 0) {
55         error_setg(errp, "Empty sequence");
56         return -1;
57     }
58     *content = value;
59     return 0;
62 /**
63  *
64  *        RsaPubKey ::= SEQUENCE {
65  *             n           INTEGER
66  *             e           INTEGER
67  *         }
68  */
69 static QCryptoAkCipherRSAKey *qcrypto_builtin_rsa_public_key_parse(
70     const uint8_t *key, size_t keylen, Error **errp)
72     QCryptoAkCipherRSAKey *rsa = g_new0(QCryptoAkCipherRSAKey, 1);
73     const uint8_t *seq;
74     size_t seq_length;
75     int decode_ret;
77     decode_ret = qcrypto_der_decode_seq(&key, &keylen,
78                                         extract_seq_content, &seq, errp);
79     if (decode_ret < 0 || keylen != 0) {
80         goto error;
81     }
82     seq_length = decode_ret;
84     if (qcrypto_der_decode_int(&seq, &seq_length, extract_mpi,
85                                &rsa->n, errp) < 0 ||
86         qcrypto_der_decode_int(&seq, &seq_length, extract_mpi,
87                                &rsa->e, errp) < 0) {
88         goto error;
89     }
90     if (seq_length != 0) {
91         goto error;
92     }
94     return rsa;
96 error:
97     if (errp && !*errp) {
98         error_setg(errp, "Invalid RSA public key");
99     }
100     qcrypto_akcipher_rsakey_free(rsa);
101     return NULL;
105  *        RsaPrivKey ::= SEQUENCE {
106  *             version     INTEGER
107  *             n           INTEGER
108  *             e           INTEGER
109  *             d           INTEGER
110  *             p           INTEGER
111  *             q           INTEGER
112  *             dp          INTEGER
113  *             dq          INTEGER
114  *             u           INTEGER
115  *       otherPrimeInfos   OtherPrimeInfos OPTIONAL
116  *         }
117  */
118 static QCryptoAkCipherRSAKey *qcrypto_builtin_rsa_private_key_parse(
119     const uint8_t *key, size_t keylen, Error **errp)
121     QCryptoAkCipherRSAKey *rsa = g_new0(QCryptoAkCipherRSAKey, 1);
122     uint8_t version;
123     const uint8_t *seq;
124     int decode_ret;
125     size_t seq_length;
127     decode_ret = qcrypto_der_decode_seq(&key, &keylen, extract_seq_content,
128                                         &seq, errp);
129     if (decode_ret < 0 || keylen != 0) {
130         goto error;
131     }
132     seq_length = decode_ret;
134     decode_ret = qcrypto_der_decode_int(&seq, &seq_length, extract_version,
135                                         &version, errp);
137     if (qcrypto_der_decode_int(&seq, &seq_length, extract_mpi,
138                                &rsa->n, errp) < 0 ||
139         qcrypto_der_decode_int(&seq, &seq_length, extract_mpi,
140                                &rsa->e, errp) < 0 ||
141         qcrypto_der_decode_int(&seq, &seq_length, extract_mpi,
142                                &rsa->d, errp) < 0 ||
143         qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, &rsa->p,
144                                errp) < 0 ||
145         qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, &rsa->q,
146                                errp) < 0 ||
147         qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, &rsa->dp,
148                                errp) < 0 ||
149         qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, &rsa->dq,
150                                errp) < 0 ||
151         qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, &rsa->u,
152                                errp) < 0) {
153         goto error;
154     }
156     /**
157      * According to the standard, otherPrimeInfos must be present for version 1.
158      * There is no strict verification here, this is to be compatible with
159      * the unit test of the kernel. TODO: remove this until linux kernel's
160      * unit-test is fixed.
161      */
162     if (version == 1 && seq_length != 0) {
163         if (qcrypto_der_decode_seq(&seq, &seq_length, NULL, NULL, errp) < 0) {
164             goto error;
165         }
166         if (seq_length != 0) {
167             goto error;
168         }
169         return rsa;
170     }
171     if (seq_length != 0) {
172         goto error;
173     }
175     return rsa;
177 error:
178     if (errp && !*errp) {
179         error_setg(errp, "Invalid RSA private key");
180     }
181     qcrypto_akcipher_rsakey_free(rsa);
182     return NULL;
185 QCryptoAkCipherRSAKey *qcrypto_akcipher_rsakey_parse(
186     QCryptoAkCipherKeyType type, const uint8_t *key,
187     size_t keylen, Error **errp)
189     switch (type) {
190     case QCRYPTO_AKCIPHER_KEY_TYPE_PRIVATE:
191         return qcrypto_builtin_rsa_private_key_parse(key, keylen, errp);
193     case QCRYPTO_AKCIPHER_KEY_TYPE_PUBLIC:
194         return qcrypto_builtin_rsa_public_key_parse(key, keylen, errp);
196     default:
197         error_setg(errp, "Unknown key type: %d", type);
198         return NULL;
199     }