xref: /qemu/crypto/rsakey-builtin.c.inc (revision 84615a19)
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 "der.h"
23#include "rsakey.h"
24
25static int extract_mpi(void *ctx, const uint8_t *value,
26                       size_t vlen, Error **errp)
27{
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;
36}
37
38static int extract_version(void *ctx, const uint8_t *value,
39                           size_t vlen, Error **errp)
40{
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;
48}
49
50static int extract_seq_content(void *ctx, const uint8_t *value,
51                               size_t vlen, Error **errp)
52{
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;
60}
61
62/**
63 *
64 *        RsaPubKey ::= SEQUENCE {
65 *             n           INTEGER
66 *             e           INTEGER
67 *         }
68 */
69static QCryptoAkCipherRSAKey *qcrypto_builtin_rsa_public_key_parse(
70    const uint8_t *key, size_t keylen, Error **errp)
71{
72    QCryptoAkCipherRSAKey *rsa = g_new0(QCryptoAkCipherRSAKey, 1);
73    const uint8_t *seq;
74    size_t seq_length;
75    int decode_ret;
76
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;
83
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    }
93
94    return rsa;
95
96error:
97    if (errp && !*errp) {
98        error_setg(errp, "Invalid RSA public key");
99    }
100    qcrypto_akcipher_rsakey_free(rsa);
101    return NULL;
102}
103
104/**
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 */
118static QCryptoAkCipherRSAKey *qcrypto_builtin_rsa_private_key_parse(
119    const uint8_t *key, size_t keylen, Error **errp)
120{
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;
126
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;
133
134    decode_ret = qcrypto_der_decode_int(&seq, &seq_length, extract_version,
135                                        &version, errp);
136
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    }
155
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    }
174
175    return rsa;
176
177error:
178    if (errp && !*errp) {
179        error_setg(errp, "Invalid RSA private key");
180    }
181    qcrypto_akcipher_rsakey_free(rsa);
182    return NULL;
183}
184
185QCryptoAkCipherRSAKey *qcrypto_akcipher_rsakey_parse(
186    QCryptoAkCipherKeyType type, const uint8_t *key,
187    size_t keylen, Error **errp)
188{
189    switch (type) {
190    case QCRYPTO_AKCIPHER_KEY_TYPE_PRIVATE:
191        return qcrypto_builtin_rsa_private_key_parse(key, keylen, errp);
192
193    case QCRYPTO_AKCIPHER_KEY_TYPE_PUBLIC:
194        return qcrypto_builtin_rsa_public_key_parse(key, keylen, errp);
195
196    default:
197        error_setg(errp, "Unknown key type: %d", type);
198        return NULL;
199    }
200}
201