2 * QEMU Crypto ASN.1 DER decoder
4 * Copyright (c) 2022 Bytedance
5 * Author: lei he <helei.sig11@bytedance.com>
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.
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.
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/>.
22 #include "qemu/osdep.h"
23 #include "crypto/der.h"
25 enum QCryptoDERTypeTag
{
26 QCRYPTO_DER_TYPE_TAG_BOOL
= 0x1,
27 QCRYPTO_DER_TYPE_TAG_INT
= 0x2,
28 QCRYPTO_DER_TYPE_TAG_BIT_STR
= 0x3,
29 QCRYPTO_DER_TYPE_TAG_OCT_STR
= 0x4,
30 QCRYPTO_DER_TYPE_TAG_OCT_NULL
= 0x5,
31 QCRYPTO_DER_TYPE_TAG_OCT_OID
= 0x6,
32 QCRYPTO_DER_TYPE_TAG_SEQ
= 0x10,
33 QCRYPTO_DER_TYPE_TAG_SET
= 0x11,
36 #define QCRYPTO_DER_CONSTRUCTED_MASK 0x20
37 #define QCRYPTO_DER_SHORT_LEN_MASK 0x80
39 static uint8_t qcrypto_der_peek_byte(const uint8_t **data
, size_t *dlen
)
44 static void qcrypto_der_cut_nbytes(const uint8_t **data
,
52 static uint8_t qcrypto_der_cut_byte(const uint8_t **data
, size_t *dlen
)
54 uint8_t val
= qcrypto_der_peek_byte(data
, dlen
);
56 qcrypto_der_cut_nbytes(data
, dlen
, 1);
61 static int qcrypto_der_invoke_callback(QCryptoDERDecodeCb cb
, void *ctx
,
62 const uint8_t *value
, size_t vlen
,
69 return cb(ctx
, value
, vlen
, errp
);
72 static int qcrypto_der_extract_definite_data(const uint8_t **data
, size_t *dlen
,
73 QCryptoDERDecodeCb cb
, void *ctx
,
78 uint8_t byte_count
= qcrypto_der_cut_byte(data
, dlen
);
80 /* short format of definite-length */
81 if (!(byte_count
& QCRYPTO_DER_SHORT_LEN_MASK
)) {
82 if (byte_count
> *dlen
) {
83 error_setg(errp
, "Invalid content length: %u", byte_count
);
89 qcrypto_der_cut_nbytes(data
, dlen
, vlen
);
91 if (qcrypto_der_invoke_callback(cb
, ctx
, value
, vlen
, errp
) != 0) {
97 /* Ignore highest bit */
98 byte_count
&= ~QCRYPTO_DER_SHORT_LEN_MASK
;
101 * size_t is enough to store the value of length, although the DER
102 * encoding standard supports larger length.
104 if (byte_count
> sizeof(size_t)) {
105 error_setg(errp
, "Invalid byte count of content length: %u",
110 if (byte_count
> *dlen
) {
111 error_setg(errp
, "Invalid content length: %u", byte_count
);
114 while (byte_count
--) {
116 vlen
+= qcrypto_der_cut_byte(data
, dlen
);
120 error_setg(errp
, "Invalid content length: %zu", vlen
);
125 qcrypto_der_cut_nbytes(data
, dlen
, vlen
);
127 if (qcrypto_der_invoke_callback(cb
, ctx
, value
, vlen
, errp
) != 0) {
133 static int qcrypto_der_extract_data(const uint8_t **data
, size_t *dlen
,
134 QCryptoDERDecodeCb cb
, void *ctx
,
139 error_setg(errp
, "Need more data");
142 val
= qcrypto_der_peek_byte(data
, dlen
);
144 /* must use definite length format */
145 if (val
== QCRYPTO_DER_SHORT_LEN_MASK
) {
146 error_setg(errp
, "Only definite length format is allowed");
150 return qcrypto_der_extract_definite_data(data
, dlen
, cb
, ctx
, errp
);
153 int qcrypto_der_decode_int(const uint8_t **data
, size_t *dlen
,
154 QCryptoDERDecodeCb cb
, void *ctx
, Error
**errp
)
158 error_setg(errp
, "Need more data");
161 tag
= qcrypto_der_cut_byte(data
, dlen
);
163 /* INTEGER must encoded in primitive-form */
164 if (tag
!= QCRYPTO_DER_TYPE_TAG_INT
) {
165 error_setg(errp
, "Invalid integer type tag: %u", tag
);
169 return qcrypto_der_extract_data(data
, dlen
, cb
, ctx
, errp
);
172 int qcrypto_der_decode_seq(const uint8_t **data
, size_t *dlen
,
173 QCryptoDERDecodeCb cb
, void *ctx
, Error
**errp
)
177 error_setg(errp
, "Need more data");
180 tag
= qcrypto_der_cut_byte(data
, dlen
);
182 /* SEQUENCE must use constructed form */
183 if (tag
!= (QCRYPTO_DER_TYPE_TAG_SEQ
| QCRYPTO_DER_CONSTRUCTED_MASK
)) {
184 error_setg(errp
, "Invalid type sequence tag: %u", tag
);
188 return qcrypto_der_extract_data(data
, dlen
, cb
, ctx
, errp
);