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 */ 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 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 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 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 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 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 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 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 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 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 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 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 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 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 3713b34ccadSLei He void qcrypto_der_encode_seq_end(QCryptoEncodeContext *ctx) 3723b34ccadSLei He { 3733b34ccadSLei He qcrypto_der_encode_cons_end(ctx); 3743b34ccadSLei He } 3753b34ccadSLei He 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 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 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 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 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 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 4243b34ccadSLei He size_t qcrypto_der_encode_ctx_buffer_len(QCryptoEncodeContext *ctx) 4253b34ccadSLei He { 4263b34ccadSLei He return ctx->root.dlen; 4273b34ccadSLei He } 4283b34ccadSLei He 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