xref: /openbmc/qemu/crypto/der.c (revision 3b34ccad)
199d423f1SLei He /*
299d423f1SLei He  * QEMU Crypto ASN.1 DER decoder
399d423f1SLei He  *
499d423f1SLei He  * Copyright (c) 2022 Bytedance
599d423f1SLei He  * Author: lei he <helei.sig11@bytedance.com>
699d423f1SLei He  *
799d423f1SLei He  * This library is free software; you can redistribute it and/or
899d423f1SLei He  * modify it under the terms of the GNU Lesser General Public
999d423f1SLei He  * License as published by the Free Software Foundation; either
1099d423f1SLei He  * version 2.1 of the License, or (at your option) any later version.
1199d423f1SLei He  *
1299d423f1SLei He  * This library is distributed in the hope that it will be useful,
1399d423f1SLei He  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1499d423f1SLei He  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1599d423f1SLei He  * Lesser General Public License for more details.
1699d423f1SLei He  *
1799d423f1SLei He  * You should have received a copy of the GNU Lesser General Public
1899d423f1SLei He  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
1999d423f1SLei He  *
2099d423f1SLei He  */
2199d423f1SLei He 
2299d423f1SLei He #include "qemu/osdep.h"
2399d423f1SLei He #include "crypto/der.h"
2499d423f1SLei He 
25*3b34ccadSLei He typedef struct QCryptoDerEncodeNode {
26*3b34ccadSLei He     uint8_t tag;
27*3b34ccadSLei He     struct QCryptoDerEncodeNode *parent;
28*3b34ccadSLei He     struct QCryptoDerEncodeNode *next;
29*3b34ccadSLei He     /* for constructed type, data is null */
30*3b34ccadSLei He     const uint8_t *data;
31*3b34ccadSLei He     size_t dlen;
32*3b34ccadSLei He } QCryptoDerEncodeNode;
33*3b34ccadSLei He 
34*3b34ccadSLei He typedef struct QCryptoEncodeContext {
35*3b34ccadSLei He     QCryptoDerEncodeNode root;
36*3b34ccadSLei He     QCryptoDerEncodeNode *current_parent;
37*3b34ccadSLei He     QCryptoDerEncodeNode *tail;
38*3b34ccadSLei He } QCryptoEncodeContext;
39*3b34ccadSLei He 
4099d423f1SLei He enum QCryptoDERTypeTag {
4199d423f1SLei He     QCRYPTO_DER_TYPE_TAG_BOOL = 0x1,
4299d423f1SLei He     QCRYPTO_DER_TYPE_TAG_INT = 0x2,
4399d423f1SLei He     QCRYPTO_DER_TYPE_TAG_BIT_STR = 0x3,
4499d423f1SLei He     QCRYPTO_DER_TYPE_TAG_OCT_STR = 0x4,
45*3b34ccadSLei He     QCRYPTO_DER_TYPE_TAG_NULL = 0x5,
46*3b34ccadSLei He     QCRYPTO_DER_TYPE_TAG_OID = 0x6,
4799d423f1SLei He     QCRYPTO_DER_TYPE_TAG_SEQ = 0x10,
4899d423f1SLei He     QCRYPTO_DER_TYPE_TAG_SET = 0x11,
4999d423f1SLei He };
5099d423f1SLei He 
51*3b34ccadSLei He enum QCryptoDERTagClass {
52*3b34ccadSLei He     QCRYPTO_DER_TAG_CLASS_UNIV = 0x0,
53*3b34ccadSLei He     QCRYPTO_DER_TAG_CLASS_APPL = 0x1,
54*3b34ccadSLei He     QCRYPTO_DER_TAG_CLASS_CONT = 0x2,
55*3b34ccadSLei He     QCRYPTO_DER_TAG_CLASS_PRIV = 0x3,
56*3b34ccadSLei He };
57*3b34ccadSLei He 
58*3b34ccadSLei He enum QCryptoDERTagEnc {
59*3b34ccadSLei He     QCRYPTO_DER_TAG_ENC_PRIM = 0x0,
60*3b34ccadSLei He     QCRYPTO_DER_TAG_ENC_CONS = 0x1,
61*3b34ccadSLei He };
62*3b34ccadSLei He 
63*3b34ccadSLei He #define QCRYPTO_DER_TAG_ENC_MASK 0x20
64*3b34ccadSLei He #define QCRYPTO_DER_TAG_ENC_SHIFT 5
65*3b34ccadSLei He 
66*3b34ccadSLei He #define QCRYPTO_DER_TAG_CLASS_MASK 0xc0
67*3b34ccadSLei He #define QCRYPTO_DER_TAG_CLASS_SHIFT 6
68*3b34ccadSLei He 
69*3b34ccadSLei He #define QCRYPTO_DER_TAG_VAL_MASK 0x1f
7099d423f1SLei He #define QCRYPTO_DER_SHORT_LEN_MASK 0x80
7199d423f1SLei He 
72*3b34ccadSLei He #define QCRYPTO_DER_TAG(class, enc, val)           \
73*3b34ccadSLei He     (((class) << QCRYPTO_DER_TAG_CLASS_SHIFT) |    \
74*3b34ccadSLei He      ((enc) << QCRYPTO_DER_TAG_ENC_SHIFT) | (val))
75*3b34ccadSLei He 
76*3b34ccadSLei He /**
77*3b34ccadSLei He  * qcrypto_der_encode_length:
78*3b34ccadSLei He  * @src_len: the length of source data
79*3b34ccadSLei He  * @dst: distination to save the encoded 'length', if dst is NULL, only compute
80*3b34ccadSLei He  * the expected buffer size in bytes.
81*3b34ccadSLei He  * @dst_len: output parameter, indicates how many bytes wrote.
82*3b34ccadSLei He  *
83*3b34ccadSLei He  * Encode the 'length' part of TLV tuple.
84*3b34ccadSLei He  */
85*3b34ccadSLei He static void qcrypto_der_encode_length(size_t src_len,
86*3b34ccadSLei He                                       uint8_t *dst, size_t *dst_len)
87*3b34ccadSLei He {
88*3b34ccadSLei He     size_t max_length = 0xFF;
89*3b34ccadSLei He     uint8_t length_bytes = 0, header_byte;
90*3b34ccadSLei He 
91*3b34ccadSLei He     if (src_len < QCRYPTO_DER_SHORT_LEN_MASK) {
92*3b34ccadSLei He         header_byte = src_len;
93*3b34ccadSLei He         *dst_len = 1;
94*3b34ccadSLei He     } else {
95*3b34ccadSLei He         for (length_bytes = 1; max_length < src_len; length_bytes++) {
96*3b34ccadSLei He             max_length = (max_length << 8) + max_length;
97*3b34ccadSLei He         }
98*3b34ccadSLei He         header_byte = length_bytes;
99*3b34ccadSLei He         header_byte |= QCRYPTO_DER_SHORT_LEN_MASK;
100*3b34ccadSLei He         *dst_len = length_bytes + 1;
101*3b34ccadSLei He     }
102*3b34ccadSLei He     if (!dst) {
103*3b34ccadSLei He         return;
104*3b34ccadSLei He     }
105*3b34ccadSLei He     *dst++ = header_byte;
106*3b34ccadSLei He     /* Bigendian length bytes */
107*3b34ccadSLei He     for (; length_bytes > 0; length_bytes--) {
108*3b34ccadSLei He         *dst++ = ((src_len >> (length_bytes - 1) * 8) & 0xFF);
109*3b34ccadSLei He     }
110*3b34ccadSLei He }
111*3b34ccadSLei He 
11299d423f1SLei He static uint8_t qcrypto_der_peek_byte(const uint8_t **data, size_t *dlen)
11399d423f1SLei He {
11499d423f1SLei He     return **data;
11599d423f1SLei He }
11699d423f1SLei He 
11799d423f1SLei He static void qcrypto_der_cut_nbytes(const uint8_t **data,
11899d423f1SLei He                                    size_t *dlen,
11999d423f1SLei He                                    size_t nbytes)
12099d423f1SLei He {
12199d423f1SLei He     *data += nbytes;
12299d423f1SLei He     *dlen -= nbytes;
12399d423f1SLei He }
12499d423f1SLei He 
12599d423f1SLei He static uint8_t qcrypto_der_cut_byte(const uint8_t **data, size_t *dlen)
12699d423f1SLei He {
12799d423f1SLei He     uint8_t val = qcrypto_der_peek_byte(data, dlen);
12899d423f1SLei He 
12999d423f1SLei He     qcrypto_der_cut_nbytes(data, dlen, 1);
13099d423f1SLei He 
13199d423f1SLei He     return val;
13299d423f1SLei He }
13399d423f1SLei He 
13499d423f1SLei He static int qcrypto_der_invoke_callback(QCryptoDERDecodeCb cb, void *ctx,
13599d423f1SLei He                                        const uint8_t *value, size_t vlen,
13699d423f1SLei He                                        Error **errp)
13799d423f1SLei He {
13899d423f1SLei He     if (!cb) {
13999d423f1SLei He         return 0;
14099d423f1SLei He     }
14199d423f1SLei He 
14299d423f1SLei He     return cb(ctx, value, vlen, errp);
14399d423f1SLei He }
14499d423f1SLei He 
14599d423f1SLei He static int qcrypto_der_extract_definite_data(const uint8_t **data, size_t *dlen,
14699d423f1SLei He                                              QCryptoDERDecodeCb cb, void *ctx,
14799d423f1SLei He                                              Error **errp)
14899d423f1SLei He {
14999d423f1SLei He     const uint8_t *value;
15099d423f1SLei He     size_t vlen = 0;
15199d423f1SLei He     uint8_t byte_count = qcrypto_der_cut_byte(data, dlen);
15299d423f1SLei He 
15399d423f1SLei He     /* short format of definite-length */
15499d423f1SLei He     if (!(byte_count & QCRYPTO_DER_SHORT_LEN_MASK)) {
15599d423f1SLei He         if (byte_count > *dlen) {
15699d423f1SLei He             error_setg(errp, "Invalid content length: %u", byte_count);
15799d423f1SLei He             return -1;
15899d423f1SLei He         }
15999d423f1SLei He 
16099d423f1SLei He         value = *data;
16199d423f1SLei He         vlen = byte_count;
16299d423f1SLei He         qcrypto_der_cut_nbytes(data, dlen, vlen);
16399d423f1SLei He 
16499d423f1SLei He         if (qcrypto_der_invoke_callback(cb, ctx, value, vlen, errp) != 0) {
16599d423f1SLei He             return -1;
16699d423f1SLei He         }
16799d423f1SLei He         return vlen;
16899d423f1SLei He     }
16999d423f1SLei He 
17099d423f1SLei He     /* Ignore highest bit */
17199d423f1SLei He     byte_count &= ~QCRYPTO_DER_SHORT_LEN_MASK;
17299d423f1SLei He 
17399d423f1SLei He     /*
17499d423f1SLei He      * size_t is enough to store the value of length, although the DER
17599d423f1SLei He      * encoding standard supports larger length.
17699d423f1SLei He      */
17799d423f1SLei He     if (byte_count > sizeof(size_t)) {
17899d423f1SLei He         error_setg(errp, "Invalid byte count of content length: %u",
17999d423f1SLei He                    byte_count);
18099d423f1SLei He         return -1;
18199d423f1SLei He     }
18299d423f1SLei He 
18399d423f1SLei He     if (byte_count > *dlen) {
18499d423f1SLei He         error_setg(errp, "Invalid content length: %u", byte_count);
18599d423f1SLei He         return -1;
18699d423f1SLei He     }
18799d423f1SLei He     while (byte_count--) {
18899d423f1SLei He         vlen <<= 8;
18999d423f1SLei He         vlen += qcrypto_der_cut_byte(data, dlen);
19099d423f1SLei He     }
19199d423f1SLei He 
19299d423f1SLei He     if (vlen > *dlen) {
19399d423f1SLei He         error_setg(errp, "Invalid content length: %zu", vlen);
19499d423f1SLei He         return -1;
19599d423f1SLei He     }
19699d423f1SLei He 
19799d423f1SLei He     value = *data;
19899d423f1SLei He     qcrypto_der_cut_nbytes(data, dlen, vlen);
19999d423f1SLei He 
20099d423f1SLei He     if (qcrypto_der_invoke_callback(cb, ctx, value, vlen, errp) != 0) {
20199d423f1SLei He         return -1;
20299d423f1SLei He     }
20399d423f1SLei He     return vlen;
20499d423f1SLei He }
20599d423f1SLei He 
20699d423f1SLei He static int qcrypto_der_extract_data(const uint8_t **data, size_t *dlen,
20799d423f1SLei He                                     QCryptoDERDecodeCb cb, void *ctx,
20899d423f1SLei He                                     Error **errp)
20999d423f1SLei He {
21099d423f1SLei He     uint8_t val;
21199d423f1SLei He     if (*dlen < 1) {
21299d423f1SLei He         error_setg(errp, "Need more data");
21399d423f1SLei He         return -1;
21499d423f1SLei He     }
21599d423f1SLei He     val = qcrypto_der_peek_byte(data, dlen);
21699d423f1SLei He 
21799d423f1SLei He     /* must use definite length format */
21899d423f1SLei He     if (val == QCRYPTO_DER_SHORT_LEN_MASK) {
21999d423f1SLei He         error_setg(errp, "Only definite length format is allowed");
22099d423f1SLei He         return -1;
22199d423f1SLei He     }
22299d423f1SLei He 
22399d423f1SLei He     return qcrypto_der_extract_definite_data(data, dlen, cb, ctx, errp);
22499d423f1SLei He }
22599d423f1SLei He 
226*3b34ccadSLei He static int qcrypto_der_decode_tlv(const uint8_t expected_tag,
227*3b34ccadSLei He                                   const uint8_t **data, size_t *dlen,
228*3b34ccadSLei He                                   QCryptoDERDecodeCb cb,
229*3b34ccadSLei He                                   void *ctx, Error **errp)
23099d423f1SLei He {
231*3b34ccadSLei He     const uint8_t *saved_data = *data;
232*3b34ccadSLei He     size_t saved_dlen = *dlen;
23399d423f1SLei He     uint8_t tag;
234*3b34ccadSLei He     int data_length;
235*3b34ccadSLei He 
23699d423f1SLei He     if (*dlen < 1) {
23799d423f1SLei He         error_setg(errp, "Need more data");
23899d423f1SLei He         return -1;
23999d423f1SLei He     }
24099d423f1SLei He     tag = qcrypto_der_cut_byte(data, dlen);
241*3b34ccadSLei He     if (tag != expected_tag) {
242*3b34ccadSLei He         error_setg(errp, "Unexpected tag: expected: %u, actual: %u",
243*3b34ccadSLei He                    expected_tag, tag);
244*3b34ccadSLei He         goto error;
245*3b34ccadSLei He     }
24699d423f1SLei He 
247*3b34ccadSLei He     data_length = qcrypto_der_extract_data(data, dlen, cb, ctx, errp);
248*3b34ccadSLei He     if (data_length < 0) {
249*3b34ccadSLei He         goto error;
250*3b34ccadSLei He     }
251*3b34ccadSLei He     return data_length;
252*3b34ccadSLei He 
253*3b34ccadSLei He error:
254*3b34ccadSLei He     *data = saved_data;
255*3b34ccadSLei He     *dlen = saved_dlen;
25699d423f1SLei He     return -1;
25799d423f1SLei He }
25899d423f1SLei He 
259*3b34ccadSLei He int qcrypto_der_decode_int(const uint8_t **data, size_t *dlen,
260*3b34ccadSLei He                            QCryptoDERDecodeCb cb, void *ctx, Error **errp)
261*3b34ccadSLei He {
262*3b34ccadSLei He     const uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
263*3b34ccadSLei He                                         QCRYPTO_DER_TAG_ENC_PRIM,
264*3b34ccadSLei He                                         QCRYPTO_DER_TYPE_TAG_INT);
265*3b34ccadSLei He     return qcrypto_der_decode_tlv(tag, data, dlen, cb, ctx, errp);
26699d423f1SLei He }
26799d423f1SLei He 
26899d423f1SLei He int qcrypto_der_decode_seq(const uint8_t **data, size_t *dlen,
26999d423f1SLei He                            QCryptoDERDecodeCb cb, void *ctx, Error **errp)
27099d423f1SLei He {
271*3b34ccadSLei He     uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
272*3b34ccadSLei He                                   QCRYPTO_DER_TAG_ENC_CONS,
273*3b34ccadSLei He                                   QCRYPTO_DER_TYPE_TAG_SEQ);
274*3b34ccadSLei He     return qcrypto_der_decode_tlv(tag, data, dlen, cb, ctx, errp);
27599d423f1SLei He }
27699d423f1SLei He 
277*3b34ccadSLei He int qcrypto_der_decode_octet_str(const uint8_t **data, size_t *dlen,
278*3b34ccadSLei He                                  QCryptoDERDecodeCb cb, void *ctx, Error **errp)
279*3b34ccadSLei He {
280*3b34ccadSLei He     uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
281*3b34ccadSLei He                                   QCRYPTO_DER_TAG_ENC_PRIM,
282*3b34ccadSLei He                                   QCRYPTO_DER_TYPE_TAG_OCT_STR);
283*3b34ccadSLei He     return qcrypto_der_decode_tlv(tag, data, dlen, cb, ctx, errp);
284*3b34ccadSLei He }
285*3b34ccadSLei He 
286*3b34ccadSLei He int qcrypto_der_decode_bit_str(const uint8_t **data, size_t *dlen,
287*3b34ccadSLei He                                QCryptoDERDecodeCb cb, void *ctx, Error **errp)
288*3b34ccadSLei He {
289*3b34ccadSLei He     uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
290*3b34ccadSLei He                                   QCRYPTO_DER_TAG_ENC_PRIM,
291*3b34ccadSLei He                                   QCRYPTO_DER_TYPE_TAG_BIT_STR);
292*3b34ccadSLei He     return qcrypto_der_decode_tlv(tag, data, dlen, cb, ctx, errp);
293*3b34ccadSLei He }
294*3b34ccadSLei He 
295*3b34ccadSLei He int qcrypto_der_decode_oid(const uint8_t **data, size_t *dlen,
296*3b34ccadSLei He                            QCryptoDERDecodeCb cb, void *ctx, Error **errp)
297*3b34ccadSLei He {
298*3b34ccadSLei He     uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
299*3b34ccadSLei He                                   QCRYPTO_DER_TAG_ENC_PRIM,
300*3b34ccadSLei He                                   QCRYPTO_DER_TYPE_TAG_OID);
301*3b34ccadSLei He     return qcrypto_der_decode_tlv(tag, data, dlen, cb, ctx, errp);
302*3b34ccadSLei He }
303*3b34ccadSLei He 
304*3b34ccadSLei He int qcrypto_der_decode_ctx_tag(const uint8_t **data, size_t *dlen, int tag_id,
305*3b34ccadSLei He                                QCryptoDERDecodeCb cb, void *ctx, Error **errp)
306*3b34ccadSLei He {
307*3b34ccadSLei He     uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_CONT,
308*3b34ccadSLei He                                   QCRYPTO_DER_TAG_ENC_CONS,
309*3b34ccadSLei He                                   tag_id);
310*3b34ccadSLei He     return qcrypto_der_decode_tlv(tag, data, dlen, cb, ctx, errp);
311*3b34ccadSLei He }
312*3b34ccadSLei He 
313*3b34ccadSLei He static void qcrypto_der_encode_prim(QCryptoEncodeContext *ctx, uint8_t tag,
314*3b34ccadSLei He                                     const uint8_t *data, size_t dlen)
315*3b34ccadSLei He {
316*3b34ccadSLei He     QCryptoDerEncodeNode *node = g_new0(QCryptoDerEncodeNode, 1);
317*3b34ccadSLei He     size_t nbytes_len;
318*3b34ccadSLei He 
319*3b34ccadSLei He     node->tag = tag;
320*3b34ccadSLei He     node->data = data;
321*3b34ccadSLei He     node->dlen = dlen;
322*3b34ccadSLei He     node->parent = ctx->current_parent;
323*3b34ccadSLei He 
324*3b34ccadSLei He     qcrypto_der_encode_length(dlen, NULL, &nbytes_len);
325*3b34ccadSLei He     /* 1 byte for Tag, nbyte_len for Length, and dlen for Value */
326*3b34ccadSLei He     node->parent->dlen += 1 + nbytes_len + dlen;
327*3b34ccadSLei He 
328*3b34ccadSLei He     ctx->tail->next = node;
329*3b34ccadSLei He     ctx->tail = node;
330*3b34ccadSLei He }
331*3b34ccadSLei He 
332*3b34ccadSLei He QCryptoEncodeContext *qcrypto_der_encode_ctx_new(void)
333*3b34ccadSLei He {
334*3b34ccadSLei He     QCryptoEncodeContext *ctx = g_new0(QCryptoEncodeContext, 1);
335*3b34ccadSLei He     ctx->current_parent = &ctx->root;
336*3b34ccadSLei He     ctx->tail = &ctx->root;
337*3b34ccadSLei He     return ctx;
338*3b34ccadSLei He }
339*3b34ccadSLei He 
340*3b34ccadSLei He static void qcrypto_der_encode_cons_begin(QCryptoEncodeContext *ctx,
341*3b34ccadSLei He                                           uint8_t tag)
342*3b34ccadSLei He {
343*3b34ccadSLei He     QCryptoDerEncodeNode *node = g_new0(QCryptoDerEncodeNode, 1);
344*3b34ccadSLei He 
345*3b34ccadSLei He     node->tag = tag;
346*3b34ccadSLei He     node->parent = ctx->current_parent;
347*3b34ccadSLei He     ctx->current_parent = node;
348*3b34ccadSLei He     ctx->tail->next = node;
349*3b34ccadSLei He     ctx->tail = node;
350*3b34ccadSLei He }
351*3b34ccadSLei He 
352*3b34ccadSLei He static void qcrypto_der_encode_cons_end(QCryptoEncodeContext *ctx)
353*3b34ccadSLei He {
354*3b34ccadSLei He     QCryptoDerEncodeNode *cons_node = ctx->current_parent;
355*3b34ccadSLei He     size_t nbytes_len;
356*3b34ccadSLei He 
357*3b34ccadSLei He     qcrypto_der_encode_length(cons_node->dlen, NULL, &nbytes_len);
358*3b34ccadSLei He     /* 1 byte for Tag, nbyte_len for Length, and dlen for Value */
359*3b34ccadSLei He     cons_node->parent->dlen += 1 + nbytes_len + cons_node->dlen;
360*3b34ccadSLei He     ctx->current_parent = cons_node->parent;
361*3b34ccadSLei He }
362*3b34ccadSLei He 
363*3b34ccadSLei He void qcrypto_der_encode_seq_begin(QCryptoEncodeContext *ctx)
364*3b34ccadSLei He {
365*3b34ccadSLei He     uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
366*3b34ccadSLei He                                   QCRYPTO_DER_TAG_ENC_CONS,
367*3b34ccadSLei He                                   QCRYPTO_DER_TYPE_TAG_SEQ);
368*3b34ccadSLei He     qcrypto_der_encode_cons_begin(ctx, tag);
369*3b34ccadSLei He }
370*3b34ccadSLei He 
371*3b34ccadSLei He void qcrypto_der_encode_seq_end(QCryptoEncodeContext *ctx)
372*3b34ccadSLei He {
373*3b34ccadSLei He     qcrypto_der_encode_cons_end(ctx);
374*3b34ccadSLei He }
375*3b34ccadSLei He 
376*3b34ccadSLei He void qcrypto_der_encode_oid(QCryptoEncodeContext *ctx,
377*3b34ccadSLei He                             const uint8_t *src, size_t src_len)
378*3b34ccadSLei He {
379*3b34ccadSLei He     uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
380*3b34ccadSLei He                                   QCRYPTO_DER_TAG_ENC_PRIM,
381*3b34ccadSLei He                                   QCRYPTO_DER_TYPE_TAG_OID);
382*3b34ccadSLei He     qcrypto_der_encode_prim(ctx, tag, src, src_len);
383*3b34ccadSLei He }
384*3b34ccadSLei He 
385*3b34ccadSLei He void qcrypto_der_encode_int(QCryptoEncodeContext *ctx,
386*3b34ccadSLei He                             const uint8_t *src, size_t src_len)
387*3b34ccadSLei He {
388*3b34ccadSLei He     uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
389*3b34ccadSLei He                                   QCRYPTO_DER_TAG_ENC_PRIM,
390*3b34ccadSLei He                                   QCRYPTO_DER_TYPE_TAG_INT);
391*3b34ccadSLei He     qcrypto_der_encode_prim(ctx, tag, src, src_len);
392*3b34ccadSLei He }
393*3b34ccadSLei He 
394*3b34ccadSLei He void qcrypto_der_encode_null(QCryptoEncodeContext *ctx)
395*3b34ccadSLei He {
396*3b34ccadSLei He     uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
397*3b34ccadSLei He                                   QCRYPTO_DER_TAG_ENC_PRIM,
398*3b34ccadSLei He                                   QCRYPTO_DER_TYPE_TAG_NULL);
399*3b34ccadSLei He     qcrypto_der_encode_prim(ctx, tag, NULL, 0);
400*3b34ccadSLei He }
401*3b34ccadSLei He 
402*3b34ccadSLei He void qcrypto_der_encode_octet_str(QCryptoEncodeContext *ctx,
403*3b34ccadSLei He                                   const uint8_t *src, size_t src_len)
404*3b34ccadSLei He {
405*3b34ccadSLei He     uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
406*3b34ccadSLei He                                   QCRYPTO_DER_TAG_ENC_PRIM,
407*3b34ccadSLei He                                   QCRYPTO_DER_TYPE_TAG_OCT_STR);
408*3b34ccadSLei He     qcrypto_der_encode_prim(ctx, tag, src, src_len);
409*3b34ccadSLei He }
410*3b34ccadSLei He 
411*3b34ccadSLei He void qcrypto_der_encode_octet_str_begin(QCryptoEncodeContext *ctx)
412*3b34ccadSLei He {
413*3b34ccadSLei He     uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
414*3b34ccadSLei He                                   QCRYPTO_DER_TAG_ENC_PRIM,
415*3b34ccadSLei He                                   QCRYPTO_DER_TYPE_TAG_OCT_STR);
416*3b34ccadSLei He     qcrypto_der_encode_cons_begin(ctx, tag);
417*3b34ccadSLei He }
418*3b34ccadSLei He 
419*3b34ccadSLei He void qcrypto_der_encode_octet_str_end(QCryptoEncodeContext *ctx)
420*3b34ccadSLei He {
421*3b34ccadSLei He     qcrypto_der_encode_cons_end(ctx);
422*3b34ccadSLei He }
423*3b34ccadSLei He 
424*3b34ccadSLei He size_t qcrypto_der_encode_ctx_buffer_len(QCryptoEncodeContext *ctx)
425*3b34ccadSLei He {
426*3b34ccadSLei He     return ctx->root.dlen;
427*3b34ccadSLei He }
428*3b34ccadSLei He 
429*3b34ccadSLei He void qcrypto_der_encode_ctx_flush_and_free(QCryptoEncodeContext *ctx,
430*3b34ccadSLei He                                            uint8_t *dst)
431*3b34ccadSLei He {
432*3b34ccadSLei He     QCryptoDerEncodeNode *node, *prev;
433*3b34ccadSLei He     size_t len;
434*3b34ccadSLei He 
435*3b34ccadSLei He     for (prev = &ctx->root;
436*3b34ccadSLei He          (node = prev->next) && (prev->next = node->next, 1);) {
437*3b34ccadSLei He         /* Tag */
438*3b34ccadSLei He         *dst++ = node->tag;
439*3b34ccadSLei He 
440*3b34ccadSLei He         /* Length */
441*3b34ccadSLei He         qcrypto_der_encode_length(node->dlen, dst, &len);
442*3b34ccadSLei He         dst += len;
443*3b34ccadSLei He 
444*3b34ccadSLei He         /* Value */
445*3b34ccadSLei He         if (node->data) {
446*3b34ccadSLei He             memcpy(dst, node->data, node->dlen);
447*3b34ccadSLei He             dst += node->dlen;
448*3b34ccadSLei He         }
449*3b34ccadSLei He         g_free(node);
450*3b34ccadSLei He     }
451*3b34ccadSLei He     g_free(ctx);
45299d423f1SLei He }
453