xref: /openbmc/qemu/crypto/der.c (revision 0a19d879)
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 
253b34ccadSLei He typedef struct QCryptoDerEncodeNode {
263b34ccadSLei He     uint8_t tag;
273b34ccadSLei He     struct QCryptoDerEncodeNode *parent;
283b34ccadSLei He     struct QCryptoDerEncodeNode *next;
293b34ccadSLei He     /* for constructed type, data is null */
303b34ccadSLei He     const uint8_t *data;
313b34ccadSLei He     size_t dlen;
323b34ccadSLei He } QCryptoDerEncodeNode;
333b34ccadSLei He 
343b34ccadSLei He typedef struct QCryptoEncodeContext {
353b34ccadSLei He     QCryptoDerEncodeNode root;
363b34ccadSLei He     QCryptoDerEncodeNode *current_parent;
373b34ccadSLei He     QCryptoDerEncodeNode *tail;
383b34ccadSLei He } QCryptoEncodeContext;
393b34ccadSLei 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,
453b34ccadSLei He     QCRYPTO_DER_TYPE_TAG_NULL = 0x5,
463b34ccadSLei 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 
513b34ccadSLei He enum QCryptoDERTagClass {
523b34ccadSLei He     QCRYPTO_DER_TAG_CLASS_UNIV = 0x0,
533b34ccadSLei He     QCRYPTO_DER_TAG_CLASS_APPL = 0x1,
543b34ccadSLei He     QCRYPTO_DER_TAG_CLASS_CONT = 0x2,
553b34ccadSLei He     QCRYPTO_DER_TAG_CLASS_PRIV = 0x3,
563b34ccadSLei He };
573b34ccadSLei He 
583b34ccadSLei He enum QCryptoDERTagEnc {
593b34ccadSLei He     QCRYPTO_DER_TAG_ENC_PRIM = 0x0,
603b34ccadSLei He     QCRYPTO_DER_TAG_ENC_CONS = 0x1,
613b34ccadSLei He };
623b34ccadSLei He 
633b34ccadSLei He #define QCRYPTO_DER_TAG_ENC_MASK 0x20
643b34ccadSLei He #define QCRYPTO_DER_TAG_ENC_SHIFT 5
653b34ccadSLei He 
663b34ccadSLei He #define QCRYPTO_DER_TAG_CLASS_MASK 0xc0
673b34ccadSLei He #define QCRYPTO_DER_TAG_CLASS_SHIFT 6
683b34ccadSLei He 
693b34ccadSLei He #define QCRYPTO_DER_TAG_VAL_MASK 0x1f
7099d423f1SLei He #define QCRYPTO_DER_SHORT_LEN_MASK 0x80
7199d423f1SLei He 
723b34ccadSLei He #define QCRYPTO_DER_TAG(class, enc, val)           \
733b34ccadSLei He     (((class) << QCRYPTO_DER_TAG_CLASS_SHIFT) |    \
743b34ccadSLei He      ((enc) << QCRYPTO_DER_TAG_ENC_SHIFT) | (val))
753b34ccadSLei He 
763b34ccadSLei He /**
773b34ccadSLei He  * qcrypto_der_encode_length:
783b34ccadSLei He  * @src_len: the length of source data
79*0a19d879SMichael Tokarev  * @dst: destination to save the encoded 'length', if dst is NULL, only compute
803b34ccadSLei He  * the expected buffer size in bytes.
813b34ccadSLei He  * @dst_len: output parameter, indicates how many bytes wrote.
823b34ccadSLei He  *
833b34ccadSLei He  * Encode the 'length' part of TLV tuple.
843b34ccadSLei He  */
qcrypto_der_encode_length(size_t src_len,uint8_t * dst,size_t * dst_len)853b34ccadSLei He static void qcrypto_der_encode_length(size_t src_len,
863b34ccadSLei He                                       uint8_t *dst, size_t *dst_len)
873b34ccadSLei He {
883b34ccadSLei He     size_t max_length = 0xFF;
893b34ccadSLei He     uint8_t length_bytes = 0, header_byte;
903b34ccadSLei He 
913b34ccadSLei He     if (src_len < QCRYPTO_DER_SHORT_LEN_MASK) {
923b34ccadSLei He         header_byte = src_len;
933b34ccadSLei He         *dst_len = 1;
943b34ccadSLei He     } else {
953b34ccadSLei He         for (length_bytes = 1; max_length < src_len; length_bytes++) {
963b34ccadSLei He             max_length = (max_length << 8) + max_length;
973b34ccadSLei He         }
983b34ccadSLei He         header_byte = length_bytes;
993b34ccadSLei He         header_byte |= QCRYPTO_DER_SHORT_LEN_MASK;
1003b34ccadSLei He         *dst_len = length_bytes + 1;
1013b34ccadSLei He     }
1023b34ccadSLei He     if (!dst) {
1033b34ccadSLei He         return;
1043b34ccadSLei He     }
1053b34ccadSLei He     *dst++ = header_byte;
1063b34ccadSLei He     /* Bigendian length bytes */
1073b34ccadSLei He     for (; length_bytes > 0; length_bytes--) {
1083b34ccadSLei He         *dst++ = ((src_len >> (length_bytes - 1) * 8) & 0xFF);
1093b34ccadSLei He     }
1103b34ccadSLei He }
1113b34ccadSLei He 
qcrypto_der_peek_byte(const uint8_t ** data,size_t * dlen)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 
qcrypto_der_cut_nbytes(const uint8_t ** data,size_t * dlen,size_t nbytes)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 
qcrypto_der_cut_byte(const uint8_t ** data,size_t * dlen)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 
qcrypto_der_invoke_callback(QCryptoDERDecodeCb cb,void * ctx,const uint8_t * value,size_t vlen,Error ** errp)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 
qcrypto_der_extract_definite_data(const uint8_t ** data,size_t * dlen,QCryptoDERDecodeCb cb,void * ctx,Error ** errp)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 
qcrypto_der_extract_data(const uint8_t ** data,size_t * dlen,QCryptoDERDecodeCb cb,void * ctx,Error ** errp)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 
qcrypto_der_decode_tlv(const uint8_t expected_tag,const uint8_t ** data,size_t * dlen,QCryptoDERDecodeCb cb,void * ctx,Error ** errp)2263b34ccadSLei He static int qcrypto_der_decode_tlv(const uint8_t expected_tag,
2273b34ccadSLei He                                   const uint8_t **data, size_t *dlen,
2283b34ccadSLei He                                   QCryptoDERDecodeCb cb,
2293b34ccadSLei He                                   void *ctx, Error **errp)
23099d423f1SLei He {
2313b34ccadSLei He     const uint8_t *saved_data = *data;
2323b34ccadSLei He     size_t saved_dlen = *dlen;
23399d423f1SLei He     uint8_t tag;
2343b34ccadSLei He     int data_length;
2353b34ccadSLei 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);
2413b34ccadSLei He     if (tag != expected_tag) {
2423b34ccadSLei He         error_setg(errp, "Unexpected tag: expected: %u, actual: %u",
2433b34ccadSLei He                    expected_tag, tag);
2443b34ccadSLei He         goto error;
2453b34ccadSLei He     }
24699d423f1SLei He 
2473b34ccadSLei He     data_length = qcrypto_der_extract_data(data, dlen, cb, ctx, errp);
2483b34ccadSLei He     if (data_length < 0) {
2493b34ccadSLei He         goto error;
2503b34ccadSLei He     }
2513b34ccadSLei He     return data_length;
2523b34ccadSLei He 
2533b34ccadSLei He error:
2543b34ccadSLei He     *data = saved_data;
2553b34ccadSLei He     *dlen = saved_dlen;
25699d423f1SLei He     return -1;
25799d423f1SLei He }
25899d423f1SLei He 
qcrypto_der_decode_int(const uint8_t ** data,size_t * dlen,QCryptoDERDecodeCb cb,void * ctx,Error ** errp)2593b34ccadSLei He int qcrypto_der_decode_int(const uint8_t **data, size_t *dlen,
2603b34ccadSLei He                            QCryptoDERDecodeCb cb, void *ctx, Error **errp)
2613b34ccadSLei He {
2623b34ccadSLei He     const uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
2633b34ccadSLei He                                         QCRYPTO_DER_TAG_ENC_PRIM,
2643b34ccadSLei He                                         QCRYPTO_DER_TYPE_TAG_INT);
2653b34ccadSLei He     return qcrypto_der_decode_tlv(tag, data, dlen, cb, ctx, errp);
26699d423f1SLei He }
26799d423f1SLei He 
qcrypto_der_decode_seq(const uint8_t ** data,size_t * dlen,QCryptoDERDecodeCb cb,void * ctx,Error ** errp)26899d423f1SLei He int qcrypto_der_decode_seq(const uint8_t **data, size_t *dlen,
26999d423f1SLei He                            QCryptoDERDecodeCb cb, void *ctx, Error **errp)
27099d423f1SLei He {
2713b34ccadSLei He     uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
2723b34ccadSLei He                                   QCRYPTO_DER_TAG_ENC_CONS,
2733b34ccadSLei He                                   QCRYPTO_DER_TYPE_TAG_SEQ);
2743b34ccadSLei He     return qcrypto_der_decode_tlv(tag, data, dlen, cb, ctx, errp);
27599d423f1SLei He }
27699d423f1SLei He 
qcrypto_der_decode_octet_str(const uint8_t ** data,size_t * dlen,QCryptoDERDecodeCb cb,void * ctx,Error ** errp)2773b34ccadSLei He int qcrypto_der_decode_octet_str(const uint8_t **data, size_t *dlen,
2783b34ccadSLei He                                  QCryptoDERDecodeCb cb, void *ctx, Error **errp)
2793b34ccadSLei He {
2803b34ccadSLei He     uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
2813b34ccadSLei He                                   QCRYPTO_DER_TAG_ENC_PRIM,
2823b34ccadSLei He                                   QCRYPTO_DER_TYPE_TAG_OCT_STR);
2833b34ccadSLei He     return qcrypto_der_decode_tlv(tag, data, dlen, cb, ctx, errp);
2843b34ccadSLei He }
2853b34ccadSLei He 
qcrypto_der_decode_bit_str(const uint8_t ** data,size_t * dlen,QCryptoDERDecodeCb cb,void * ctx,Error ** errp)2863b34ccadSLei He int qcrypto_der_decode_bit_str(const uint8_t **data, size_t *dlen,
2873b34ccadSLei He                                QCryptoDERDecodeCb cb, void *ctx, Error **errp)
2883b34ccadSLei He {
2893b34ccadSLei He     uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
2903b34ccadSLei He                                   QCRYPTO_DER_TAG_ENC_PRIM,
2913b34ccadSLei He                                   QCRYPTO_DER_TYPE_TAG_BIT_STR);
2923b34ccadSLei He     return qcrypto_der_decode_tlv(tag, data, dlen, cb, ctx, errp);
2933b34ccadSLei He }
2943b34ccadSLei He 
qcrypto_der_decode_oid(const uint8_t ** data,size_t * dlen,QCryptoDERDecodeCb cb,void * ctx,Error ** errp)2953b34ccadSLei He int qcrypto_der_decode_oid(const uint8_t **data, size_t *dlen,
2963b34ccadSLei He                            QCryptoDERDecodeCb cb, void *ctx, Error **errp)
2973b34ccadSLei He {
2983b34ccadSLei He     uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
2993b34ccadSLei He                                   QCRYPTO_DER_TAG_ENC_PRIM,
3003b34ccadSLei He                                   QCRYPTO_DER_TYPE_TAG_OID);
3013b34ccadSLei He     return qcrypto_der_decode_tlv(tag, data, dlen, cb, ctx, errp);
3023b34ccadSLei He }
3033b34ccadSLei He 
qcrypto_der_decode_ctx_tag(const uint8_t ** data,size_t * dlen,int tag_id,QCryptoDERDecodeCb cb,void * ctx,Error ** errp)3043b34ccadSLei He int qcrypto_der_decode_ctx_tag(const uint8_t **data, size_t *dlen, int tag_id,
3053b34ccadSLei He                                QCryptoDERDecodeCb cb, void *ctx, Error **errp)
3063b34ccadSLei He {
3073b34ccadSLei He     uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_CONT,
3083b34ccadSLei He                                   QCRYPTO_DER_TAG_ENC_CONS,
3093b34ccadSLei He                                   tag_id);
3103b34ccadSLei He     return qcrypto_der_decode_tlv(tag, data, dlen, cb, ctx, errp);
3113b34ccadSLei He }
3123b34ccadSLei He 
qcrypto_der_encode_prim(QCryptoEncodeContext * ctx,uint8_t tag,const uint8_t * data,size_t dlen)3133b34ccadSLei He static void qcrypto_der_encode_prim(QCryptoEncodeContext *ctx, uint8_t tag,
3143b34ccadSLei He                                     const uint8_t *data, size_t dlen)
3153b34ccadSLei He {
3163b34ccadSLei He     QCryptoDerEncodeNode *node = g_new0(QCryptoDerEncodeNode, 1);
3173b34ccadSLei He     size_t nbytes_len;
3183b34ccadSLei He 
3193b34ccadSLei He     node->tag = tag;
3203b34ccadSLei He     node->data = data;
3213b34ccadSLei He     node->dlen = dlen;
3223b34ccadSLei He     node->parent = ctx->current_parent;
3233b34ccadSLei He 
3243b34ccadSLei He     qcrypto_der_encode_length(dlen, NULL, &nbytes_len);
3253b34ccadSLei He     /* 1 byte for Tag, nbyte_len for Length, and dlen for Value */
3263b34ccadSLei He     node->parent->dlen += 1 + nbytes_len + dlen;
3273b34ccadSLei He 
3283b34ccadSLei He     ctx->tail->next = node;
3293b34ccadSLei He     ctx->tail = node;
3303b34ccadSLei He }
3313b34ccadSLei He 
qcrypto_der_encode_ctx_new(void)3323b34ccadSLei He QCryptoEncodeContext *qcrypto_der_encode_ctx_new(void)
3333b34ccadSLei He {
3343b34ccadSLei He     QCryptoEncodeContext *ctx = g_new0(QCryptoEncodeContext, 1);
3353b34ccadSLei He     ctx->current_parent = &ctx->root;
3363b34ccadSLei He     ctx->tail = &ctx->root;
3373b34ccadSLei He     return ctx;
3383b34ccadSLei He }
3393b34ccadSLei He 
qcrypto_der_encode_cons_begin(QCryptoEncodeContext * ctx,uint8_t tag)3403b34ccadSLei He static void qcrypto_der_encode_cons_begin(QCryptoEncodeContext *ctx,
3413b34ccadSLei He                                           uint8_t tag)
3423b34ccadSLei He {
3433b34ccadSLei He     QCryptoDerEncodeNode *node = g_new0(QCryptoDerEncodeNode, 1);
3443b34ccadSLei He 
3453b34ccadSLei He     node->tag = tag;
3463b34ccadSLei He     node->parent = ctx->current_parent;
3473b34ccadSLei He     ctx->current_parent = node;
3483b34ccadSLei He     ctx->tail->next = node;
3493b34ccadSLei He     ctx->tail = node;
3503b34ccadSLei He }
3513b34ccadSLei He 
qcrypto_der_encode_cons_end(QCryptoEncodeContext * ctx)3523b34ccadSLei He static void qcrypto_der_encode_cons_end(QCryptoEncodeContext *ctx)
3533b34ccadSLei He {
3543b34ccadSLei He     QCryptoDerEncodeNode *cons_node = ctx->current_parent;
3553b34ccadSLei He     size_t nbytes_len;
3563b34ccadSLei He 
3573b34ccadSLei He     qcrypto_der_encode_length(cons_node->dlen, NULL, &nbytes_len);
3583b34ccadSLei He     /* 1 byte for Tag, nbyte_len for Length, and dlen for Value */
3593b34ccadSLei He     cons_node->parent->dlen += 1 + nbytes_len + cons_node->dlen;
3603b34ccadSLei He     ctx->current_parent = cons_node->parent;
3613b34ccadSLei He }
3623b34ccadSLei He 
qcrypto_der_encode_seq_begin(QCryptoEncodeContext * ctx)3633b34ccadSLei He void qcrypto_der_encode_seq_begin(QCryptoEncodeContext *ctx)
3643b34ccadSLei He {
3653b34ccadSLei He     uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
3663b34ccadSLei He                                   QCRYPTO_DER_TAG_ENC_CONS,
3673b34ccadSLei He                                   QCRYPTO_DER_TYPE_TAG_SEQ);
3683b34ccadSLei He     qcrypto_der_encode_cons_begin(ctx, tag);
3693b34ccadSLei He }
3703b34ccadSLei He 
qcrypto_der_encode_seq_end(QCryptoEncodeContext * ctx)3713b34ccadSLei He void qcrypto_der_encode_seq_end(QCryptoEncodeContext *ctx)
3723b34ccadSLei He {
3733b34ccadSLei He     qcrypto_der_encode_cons_end(ctx);
3743b34ccadSLei He }
3753b34ccadSLei He 
qcrypto_der_encode_oid(QCryptoEncodeContext * ctx,const uint8_t * src,size_t src_len)3763b34ccadSLei He void qcrypto_der_encode_oid(QCryptoEncodeContext *ctx,
3773b34ccadSLei He                             const uint8_t *src, size_t src_len)
3783b34ccadSLei He {
3793b34ccadSLei He     uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
3803b34ccadSLei He                                   QCRYPTO_DER_TAG_ENC_PRIM,
3813b34ccadSLei He                                   QCRYPTO_DER_TYPE_TAG_OID);
3823b34ccadSLei He     qcrypto_der_encode_prim(ctx, tag, src, src_len);
3833b34ccadSLei He }
3843b34ccadSLei He 
qcrypto_der_encode_int(QCryptoEncodeContext * ctx,const uint8_t * src,size_t src_len)3853b34ccadSLei He void qcrypto_der_encode_int(QCryptoEncodeContext *ctx,
3863b34ccadSLei He                             const uint8_t *src, size_t src_len)
3873b34ccadSLei He {
3883b34ccadSLei He     uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
3893b34ccadSLei He                                   QCRYPTO_DER_TAG_ENC_PRIM,
3903b34ccadSLei He                                   QCRYPTO_DER_TYPE_TAG_INT);
3913b34ccadSLei He     qcrypto_der_encode_prim(ctx, tag, src, src_len);
3923b34ccadSLei He }
3933b34ccadSLei He 
qcrypto_der_encode_null(QCryptoEncodeContext * ctx)3943b34ccadSLei He void qcrypto_der_encode_null(QCryptoEncodeContext *ctx)
3953b34ccadSLei He {
3963b34ccadSLei He     uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
3973b34ccadSLei He                                   QCRYPTO_DER_TAG_ENC_PRIM,
3983b34ccadSLei He                                   QCRYPTO_DER_TYPE_TAG_NULL);
3993b34ccadSLei He     qcrypto_der_encode_prim(ctx, tag, NULL, 0);
4003b34ccadSLei He }
4013b34ccadSLei He 
qcrypto_der_encode_octet_str(QCryptoEncodeContext * ctx,const uint8_t * src,size_t src_len)4023b34ccadSLei He void qcrypto_der_encode_octet_str(QCryptoEncodeContext *ctx,
4033b34ccadSLei He                                   const uint8_t *src, size_t src_len)
4043b34ccadSLei He {
4053b34ccadSLei He     uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
4063b34ccadSLei He                                   QCRYPTO_DER_TAG_ENC_PRIM,
4073b34ccadSLei He                                   QCRYPTO_DER_TYPE_TAG_OCT_STR);
4083b34ccadSLei He     qcrypto_der_encode_prim(ctx, tag, src, src_len);
4093b34ccadSLei He }
4103b34ccadSLei He 
qcrypto_der_encode_octet_str_begin(QCryptoEncodeContext * ctx)4113b34ccadSLei He void qcrypto_der_encode_octet_str_begin(QCryptoEncodeContext *ctx)
4123b34ccadSLei He {
4133b34ccadSLei He     uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
4143b34ccadSLei He                                   QCRYPTO_DER_TAG_ENC_PRIM,
4153b34ccadSLei He                                   QCRYPTO_DER_TYPE_TAG_OCT_STR);
4163b34ccadSLei He     qcrypto_der_encode_cons_begin(ctx, tag);
4173b34ccadSLei He }
4183b34ccadSLei He 
qcrypto_der_encode_octet_str_end(QCryptoEncodeContext * ctx)4193b34ccadSLei He void qcrypto_der_encode_octet_str_end(QCryptoEncodeContext *ctx)
4203b34ccadSLei He {
4213b34ccadSLei He     qcrypto_der_encode_cons_end(ctx);
4223b34ccadSLei He }
4233b34ccadSLei He 
qcrypto_der_encode_ctx_buffer_len(QCryptoEncodeContext * ctx)4243b34ccadSLei He size_t qcrypto_der_encode_ctx_buffer_len(QCryptoEncodeContext *ctx)
4253b34ccadSLei He {
4263b34ccadSLei He     return ctx->root.dlen;
4273b34ccadSLei He }
4283b34ccadSLei He 
qcrypto_der_encode_ctx_flush_and_free(QCryptoEncodeContext * ctx,uint8_t * dst)4293b34ccadSLei He void qcrypto_der_encode_ctx_flush_and_free(QCryptoEncodeContext *ctx,
4303b34ccadSLei He                                            uint8_t *dst)
4313b34ccadSLei He {
4323b34ccadSLei He     QCryptoDerEncodeNode *node, *prev;
4333b34ccadSLei He     size_t len;
4343b34ccadSLei He 
4353b34ccadSLei He     for (prev = &ctx->root;
4363b34ccadSLei He          (node = prev->next) && (prev->next = node->next, 1);) {
4373b34ccadSLei He         /* Tag */
4383b34ccadSLei He         *dst++ = node->tag;
4393b34ccadSLei He 
4403b34ccadSLei He         /* Length */
4413b34ccadSLei He         qcrypto_der_encode_length(node->dlen, dst, &len);
4423b34ccadSLei He         dst += len;
4433b34ccadSLei He 
4443b34ccadSLei He         /* Value */
4453b34ccadSLei He         if (node->data) {
4463b34ccadSLei He             memcpy(dst, node->data, node->dlen);
4473b34ccadSLei He             dst += node->dlen;
4483b34ccadSLei He         }
4493b34ccadSLei He         g_free(node);
4503b34ccadSLei He     }
4513b34ccadSLei He     g_free(ctx);
45299d423f1SLei He }
453