blob: 6337b84c54ee928030d0575f059a983b1a0ba617 [file] [log] [blame]
Lei He4c5e5122022-05-25 17:01:14 +08001/*
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) {
Markus Armbrustere158f8e2023-09-01 14:32:26 +020091 error_setg(errp, "Invalid RSA public key");
Lei He4c5e5122022-05-25 17:01:14 +080092 goto error;
93 }
94
95 return rsa;
96
97error:
Lei He4c5e5122022-05-25 17:01:14 +080098 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) {
Markus Armbrustere158f8e2023-09-01 14:32:26 +0200170 error_setg(errp, "Invalid RSA private key");
Lei He4c5e5122022-05-25 17:01:14 +0800171 goto error;
172 }
173
174 return rsa;
175
176error:
Lei He4c5e5122022-05-25 17:01:14 +0800177 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) {
Markus Armbruster5f4059e2024-09-04 13:18:27 +0200186 case QCRYPTO_AK_CIPHER_KEY_TYPE_PRIVATE:
Lei He4c5e5122022-05-25 17:01:14 +0800187 return qcrypto_builtin_rsa_private_key_parse(key, keylen, errp);
188
Markus Armbruster5f4059e2024-09-04 13:18:27 +0200189 case QCRYPTO_AK_CIPHER_KEY_TYPE_PUBLIC:
Lei He4c5e5122022-05-25 17:01:14 +0800190 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}