xref: /openbmc/qemu/crypto/der.c (revision 99d423f1)
1*99d423f1SLei He /*
2*99d423f1SLei He  * QEMU Crypto ASN.1 DER decoder
3*99d423f1SLei He  *
4*99d423f1SLei He  * Copyright (c) 2022 Bytedance
5*99d423f1SLei He  * Author: lei he <helei.sig11@bytedance.com>
6*99d423f1SLei He  *
7*99d423f1SLei He  * This library is free software; you can redistribute it and/or
8*99d423f1SLei He  * modify it under the terms of the GNU Lesser General Public
9*99d423f1SLei He  * License as published by the Free Software Foundation; either
10*99d423f1SLei He  * version 2.1 of the License, or (at your option) any later version.
11*99d423f1SLei He  *
12*99d423f1SLei He  * This library is distributed in the hope that it will be useful,
13*99d423f1SLei He  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14*99d423f1SLei He  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15*99d423f1SLei He  * Lesser General Public License for more details.
16*99d423f1SLei He  *
17*99d423f1SLei He  * You should have received a copy of the GNU Lesser General Public
18*99d423f1SLei He  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19*99d423f1SLei He  *
20*99d423f1SLei He  */
21*99d423f1SLei He 
22*99d423f1SLei He #include "qemu/osdep.h"
23*99d423f1SLei He #include "crypto/der.h"
24*99d423f1SLei He 
25*99d423f1SLei He enum QCryptoDERTypeTag {
26*99d423f1SLei He     QCRYPTO_DER_TYPE_TAG_BOOL = 0x1,
27*99d423f1SLei He     QCRYPTO_DER_TYPE_TAG_INT = 0x2,
28*99d423f1SLei He     QCRYPTO_DER_TYPE_TAG_BIT_STR = 0x3,
29*99d423f1SLei He     QCRYPTO_DER_TYPE_TAG_OCT_STR = 0x4,
30*99d423f1SLei He     QCRYPTO_DER_TYPE_TAG_OCT_NULL = 0x5,
31*99d423f1SLei He     QCRYPTO_DER_TYPE_TAG_OCT_OID = 0x6,
32*99d423f1SLei He     QCRYPTO_DER_TYPE_TAG_SEQ = 0x10,
33*99d423f1SLei He     QCRYPTO_DER_TYPE_TAG_SET = 0x11,
34*99d423f1SLei He };
35*99d423f1SLei He 
36*99d423f1SLei He #define QCRYPTO_DER_CONSTRUCTED_MASK 0x20
37*99d423f1SLei He #define QCRYPTO_DER_SHORT_LEN_MASK 0x80
38*99d423f1SLei He 
39*99d423f1SLei He static uint8_t qcrypto_der_peek_byte(const uint8_t **data, size_t *dlen)
40*99d423f1SLei He {
41*99d423f1SLei He     return **data;
42*99d423f1SLei He }
43*99d423f1SLei He 
44*99d423f1SLei He static void qcrypto_der_cut_nbytes(const uint8_t **data,
45*99d423f1SLei He                                    size_t *dlen,
46*99d423f1SLei He                                    size_t nbytes)
47*99d423f1SLei He {
48*99d423f1SLei He     *data += nbytes;
49*99d423f1SLei He     *dlen -= nbytes;
50*99d423f1SLei He }
51*99d423f1SLei He 
52*99d423f1SLei He static uint8_t qcrypto_der_cut_byte(const uint8_t **data, size_t *dlen)
53*99d423f1SLei He {
54*99d423f1SLei He     uint8_t val = qcrypto_der_peek_byte(data, dlen);
55*99d423f1SLei He 
56*99d423f1SLei He     qcrypto_der_cut_nbytes(data, dlen, 1);
57*99d423f1SLei He 
58*99d423f1SLei He     return val;
59*99d423f1SLei He }
60*99d423f1SLei He 
61*99d423f1SLei He static int qcrypto_der_invoke_callback(QCryptoDERDecodeCb cb, void *ctx,
62*99d423f1SLei He                                        const uint8_t *value, size_t vlen,
63*99d423f1SLei He                                        Error **errp)
64*99d423f1SLei He {
65*99d423f1SLei He     if (!cb) {
66*99d423f1SLei He         return 0;
67*99d423f1SLei He     }
68*99d423f1SLei He 
69*99d423f1SLei He     return cb(ctx, value, vlen, errp);
70*99d423f1SLei He }
71*99d423f1SLei He 
72*99d423f1SLei He static int qcrypto_der_extract_definite_data(const uint8_t **data, size_t *dlen,
73*99d423f1SLei He                                              QCryptoDERDecodeCb cb, void *ctx,
74*99d423f1SLei He                                              Error **errp)
75*99d423f1SLei He {
76*99d423f1SLei He     const uint8_t *value;
77*99d423f1SLei He     size_t vlen = 0;
78*99d423f1SLei He     uint8_t byte_count = qcrypto_der_cut_byte(data, dlen);
79*99d423f1SLei He 
80*99d423f1SLei He     /* short format of definite-length */
81*99d423f1SLei He     if (!(byte_count & QCRYPTO_DER_SHORT_LEN_MASK)) {
82*99d423f1SLei He         if (byte_count > *dlen) {
83*99d423f1SLei He             error_setg(errp, "Invalid content length: %u", byte_count);
84*99d423f1SLei He             return -1;
85*99d423f1SLei He         }
86*99d423f1SLei He 
87*99d423f1SLei He         value = *data;
88*99d423f1SLei He         vlen = byte_count;
89*99d423f1SLei He         qcrypto_der_cut_nbytes(data, dlen, vlen);
90*99d423f1SLei He 
91*99d423f1SLei He         if (qcrypto_der_invoke_callback(cb, ctx, value, vlen, errp) != 0) {
92*99d423f1SLei He             return -1;
93*99d423f1SLei He         }
94*99d423f1SLei He         return vlen;
95*99d423f1SLei He     }
96*99d423f1SLei He 
97*99d423f1SLei He     /* Ignore highest bit */
98*99d423f1SLei He     byte_count &= ~QCRYPTO_DER_SHORT_LEN_MASK;
99*99d423f1SLei He 
100*99d423f1SLei He     /*
101*99d423f1SLei He      * size_t is enough to store the value of length, although the DER
102*99d423f1SLei He      * encoding standard supports larger length.
103*99d423f1SLei He      */
104*99d423f1SLei He     if (byte_count > sizeof(size_t)) {
105*99d423f1SLei He         error_setg(errp, "Invalid byte count of content length: %u",
106*99d423f1SLei He                    byte_count);
107*99d423f1SLei He         return -1;
108*99d423f1SLei He     }
109*99d423f1SLei He 
110*99d423f1SLei He     if (byte_count > *dlen) {
111*99d423f1SLei He         error_setg(errp, "Invalid content length: %u", byte_count);
112*99d423f1SLei He         return -1;
113*99d423f1SLei He     }
114*99d423f1SLei He     while (byte_count--) {
115*99d423f1SLei He         vlen <<= 8;
116*99d423f1SLei He         vlen += qcrypto_der_cut_byte(data, dlen);
117*99d423f1SLei He     }
118*99d423f1SLei He 
119*99d423f1SLei He     if (vlen > *dlen) {
120*99d423f1SLei He         error_setg(errp, "Invalid content length: %zu", vlen);
121*99d423f1SLei He         return -1;
122*99d423f1SLei He     }
123*99d423f1SLei He 
124*99d423f1SLei He     value = *data;
125*99d423f1SLei He     qcrypto_der_cut_nbytes(data, dlen, vlen);
126*99d423f1SLei He 
127*99d423f1SLei He     if (qcrypto_der_invoke_callback(cb, ctx, value, vlen, errp) != 0) {
128*99d423f1SLei He         return -1;
129*99d423f1SLei He     }
130*99d423f1SLei He     return vlen;
131*99d423f1SLei He }
132*99d423f1SLei He 
133*99d423f1SLei He static int qcrypto_der_extract_data(const uint8_t **data, size_t *dlen,
134*99d423f1SLei He                                     QCryptoDERDecodeCb cb, void *ctx,
135*99d423f1SLei He                                     Error **errp)
136*99d423f1SLei He {
137*99d423f1SLei He     uint8_t val;
138*99d423f1SLei He     if (*dlen < 1) {
139*99d423f1SLei He         error_setg(errp, "Need more data");
140*99d423f1SLei He         return -1;
141*99d423f1SLei He     }
142*99d423f1SLei He     val = qcrypto_der_peek_byte(data, dlen);
143*99d423f1SLei He 
144*99d423f1SLei He     /* must use definite length format */
145*99d423f1SLei He     if (val == QCRYPTO_DER_SHORT_LEN_MASK) {
146*99d423f1SLei He         error_setg(errp, "Only definite length format is allowed");
147*99d423f1SLei He         return -1;
148*99d423f1SLei He     }
149*99d423f1SLei He 
150*99d423f1SLei He     return qcrypto_der_extract_definite_data(data, dlen, cb, ctx, errp);
151*99d423f1SLei He }
152*99d423f1SLei He 
153*99d423f1SLei He int qcrypto_der_decode_int(const uint8_t **data, size_t *dlen,
154*99d423f1SLei He                            QCryptoDERDecodeCb cb, void *ctx, Error **errp)
155*99d423f1SLei He {
156*99d423f1SLei He     uint8_t tag;
157*99d423f1SLei He     if (*dlen < 1) {
158*99d423f1SLei He         error_setg(errp, "Need more data");
159*99d423f1SLei He         return -1;
160*99d423f1SLei He     }
161*99d423f1SLei He     tag = qcrypto_der_cut_byte(data, dlen);
162*99d423f1SLei He 
163*99d423f1SLei He     /* INTEGER must encoded in primitive-form */
164*99d423f1SLei He     if (tag != QCRYPTO_DER_TYPE_TAG_INT) {
165*99d423f1SLei He         error_setg(errp, "Invalid integer type tag: %u", tag);
166*99d423f1SLei He         return -1;
167*99d423f1SLei He     }
168*99d423f1SLei He 
169*99d423f1SLei He     return qcrypto_der_extract_data(data, dlen, cb, ctx, errp);
170*99d423f1SLei He }
171*99d423f1SLei He 
172*99d423f1SLei He int qcrypto_der_decode_seq(const uint8_t **data, size_t *dlen,
173*99d423f1SLei He                            QCryptoDERDecodeCb cb, void *ctx, Error **errp)
174*99d423f1SLei He {
175*99d423f1SLei He     uint8_t tag;
176*99d423f1SLei He     if (*dlen < 1) {
177*99d423f1SLei He         error_setg(errp, "Need more data");
178*99d423f1SLei He         return -1;
179*99d423f1SLei He     }
180*99d423f1SLei He     tag = qcrypto_der_cut_byte(data, dlen);
181*99d423f1SLei He 
182*99d423f1SLei He     /* SEQUENCE must use constructed form */
183*99d423f1SLei He     if (tag != (QCRYPTO_DER_TYPE_TAG_SEQ | QCRYPTO_DER_CONSTRUCTED_MASK)) {
184*99d423f1SLei He         error_setg(errp, "Invalid type sequence tag: %u", tag);
185*99d423f1SLei He         return -1;
186*99d423f1SLei He     }
187*99d423f1SLei He 
188*99d423f1SLei He     return qcrypto_der_extract_data(data, dlen, cb, ctx, errp);
189*99d423f1SLei He }
190