xref: /openbmc/qemu/crypto/rsakey-builtin.c.inc (revision e53c136f)
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        error_setg(errp, "Invalid RSA public key");
92        goto error;
93    }
94
95    return rsa;
96
97error:
98    qcrypto_akcipher_rsakey_free(rsa);
99    return NULL;
100}
101
102/**
103 *        RsaPrivKey ::= SEQUENCE {
104 *             version     INTEGER
105 *             n           INTEGER
106 *             e           INTEGER
107 *             d           INTEGER
108 *             p           INTEGER
109 *             q           INTEGER
110 *             dp          INTEGER
111 *             dq          INTEGER
112 *             u           INTEGER
113 *       otherPrimeInfos   OtherPrimeInfos OPTIONAL
114 *         }
115 */
116static QCryptoAkCipherRSAKey *qcrypto_builtin_rsa_private_key_parse(
117    const uint8_t *key, size_t keylen, Error **errp)
118{
119    QCryptoAkCipherRSAKey *rsa = g_new0(QCryptoAkCipherRSAKey, 1);
120    uint8_t version;
121    const uint8_t *seq;
122    int decode_ret;
123    size_t seq_length;
124
125    decode_ret = qcrypto_der_decode_seq(&key, &keylen, extract_seq_content,
126                                        &seq, errp);
127    if (decode_ret < 0 || keylen != 0) {
128        goto error;
129    }
130    seq_length = decode_ret;
131
132    decode_ret = qcrypto_der_decode_int(&seq, &seq_length, extract_version,
133                                        &version, errp);
134
135    if (qcrypto_der_decode_int(&seq, &seq_length, extract_mpi,
136                               &rsa->n, errp) < 0 ||
137        qcrypto_der_decode_int(&seq, &seq_length, extract_mpi,
138                               &rsa->e, errp) < 0 ||
139        qcrypto_der_decode_int(&seq, &seq_length, extract_mpi,
140                               &rsa->d, errp) < 0 ||
141        qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, &rsa->p,
142                               errp) < 0 ||
143        qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, &rsa->q,
144                               errp) < 0 ||
145        qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, &rsa->dp,
146                               errp) < 0 ||
147        qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, &rsa->dq,
148                               errp) < 0 ||
149        qcrypto_der_decode_int(&seq, &seq_length, extract_mpi, &rsa->u,
150                               errp) < 0) {
151        goto error;
152    }
153
154    /**
155     * According to the standard, otherPrimeInfos must be present for version 1.
156     * There is no strict verification here, this is to be compatible with
157     * the unit test of the kernel. TODO: remove this until linux kernel's
158     * unit-test is fixed.
159     */
160    if (version == 1 && seq_length != 0) {
161        if (qcrypto_der_decode_seq(&seq, &seq_length, NULL, NULL, errp) < 0) {
162            goto error;
163        }
164        if (seq_length != 0) {
165            goto error;
166        }
167        return rsa;
168    }
169    if (seq_length != 0) {
170        error_setg(errp, "Invalid RSA private key");
171        goto error;
172    }
173
174    return rsa;
175
176error:
177    qcrypto_akcipher_rsakey_free(rsa);
178    return NULL;
179}
180
181QCryptoAkCipherRSAKey *qcrypto_akcipher_rsakey_parse(
182    QCryptoAkCipherKeyType type, const uint8_t *key,
183    size_t keylen, Error **errp)
184{
185    switch (type) {
186    case QCRYPTO_AK_CIPHER_KEY_TYPE_PRIVATE:
187        return qcrypto_builtin_rsa_private_key_parse(key, keylen, errp);
188
189    case QCRYPTO_AK_CIPHER_KEY_TYPE_PUBLIC:
190        return qcrypto_builtin_rsa_public_key_parse(key, keylen, errp);
191
192    default:
193        error_setg(errp, "Unknown key type: %d", type);
194        return NULL;
195    }
196}
197