qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

der.c (14153B)


      1 /*
      2  * QEMU Crypto ASN.1 DER decoder
      3  *
      4  * Copyright (c) 2022 Bytedance
      5  * Author: lei he <helei.sig11@bytedance.com>
      6  *
      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.
     11  *
     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.
     16  *
     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/>.
     19  *
     20  */
     21 
     22 #include "qemu/osdep.h"
     23 #include "crypto/der.h"
     24 
     25 typedef struct QCryptoDerEncodeNode {
     26     uint8_t tag;
     27     struct QCryptoDerEncodeNode *parent;
     28     struct QCryptoDerEncodeNode *next;
     29     /* for constructed type, data is null */
     30     const uint8_t *data;
     31     size_t dlen;
     32 } QCryptoDerEncodeNode;
     33 
     34 typedef struct QCryptoEncodeContext {
     35     QCryptoDerEncodeNode root;
     36     QCryptoDerEncodeNode *current_parent;
     37     QCryptoDerEncodeNode *tail;
     38 } QCryptoEncodeContext;
     39 
     40 enum QCryptoDERTypeTag {
     41     QCRYPTO_DER_TYPE_TAG_BOOL = 0x1,
     42     QCRYPTO_DER_TYPE_TAG_INT = 0x2,
     43     QCRYPTO_DER_TYPE_TAG_BIT_STR = 0x3,
     44     QCRYPTO_DER_TYPE_TAG_OCT_STR = 0x4,
     45     QCRYPTO_DER_TYPE_TAG_NULL = 0x5,
     46     QCRYPTO_DER_TYPE_TAG_OID = 0x6,
     47     QCRYPTO_DER_TYPE_TAG_SEQ = 0x10,
     48     QCRYPTO_DER_TYPE_TAG_SET = 0x11,
     49 };
     50 
     51 enum QCryptoDERTagClass {
     52     QCRYPTO_DER_TAG_CLASS_UNIV = 0x0,
     53     QCRYPTO_DER_TAG_CLASS_APPL = 0x1,
     54     QCRYPTO_DER_TAG_CLASS_CONT = 0x2,
     55     QCRYPTO_DER_TAG_CLASS_PRIV = 0x3,
     56 };
     57 
     58 enum QCryptoDERTagEnc {
     59     QCRYPTO_DER_TAG_ENC_PRIM = 0x0,
     60     QCRYPTO_DER_TAG_ENC_CONS = 0x1,
     61 };
     62 
     63 #define QCRYPTO_DER_TAG_ENC_MASK 0x20
     64 #define QCRYPTO_DER_TAG_ENC_SHIFT 5
     65 
     66 #define QCRYPTO_DER_TAG_CLASS_MASK 0xc0
     67 #define QCRYPTO_DER_TAG_CLASS_SHIFT 6
     68 
     69 #define QCRYPTO_DER_TAG_VAL_MASK 0x1f
     70 #define QCRYPTO_DER_SHORT_LEN_MASK 0x80
     71 
     72 #define QCRYPTO_DER_TAG(class, enc, val)           \
     73     (((class) << QCRYPTO_DER_TAG_CLASS_SHIFT) |    \
     74      ((enc) << QCRYPTO_DER_TAG_ENC_SHIFT) | (val))
     75 
     76 /**
     77  * qcrypto_der_encode_length:
     78  * @src_len: the length of source data
     79  * @dst: distination to save the encoded 'length', if dst is NULL, only compute
     80  * the expected buffer size in bytes.
     81  * @dst_len: output parameter, indicates how many bytes wrote.
     82  *
     83  * Encode the 'length' part of TLV tuple.
     84  */
     85 static void qcrypto_der_encode_length(size_t src_len,
     86                                       uint8_t *dst, size_t *dst_len)
     87 {
     88     size_t max_length = 0xFF;
     89     uint8_t length_bytes = 0, header_byte;
     90 
     91     if (src_len < QCRYPTO_DER_SHORT_LEN_MASK) {
     92         header_byte = src_len;
     93         *dst_len = 1;
     94     } else {
     95         for (length_bytes = 1; max_length < src_len; length_bytes++) {
     96             max_length = (max_length << 8) + max_length;
     97         }
     98         header_byte = length_bytes;
     99         header_byte |= QCRYPTO_DER_SHORT_LEN_MASK;
    100         *dst_len = length_bytes + 1;
    101     }
    102     if (!dst) {
    103         return;
    104     }
    105     *dst++ = header_byte;
    106     /* Bigendian length bytes */
    107     for (; length_bytes > 0; length_bytes--) {
    108         *dst++ = ((src_len >> (length_bytes - 1) * 8) & 0xFF);
    109     }
    110 }
    111 
    112 static uint8_t qcrypto_der_peek_byte(const uint8_t **data, size_t *dlen)
    113 {
    114     return **data;
    115 }
    116 
    117 static void qcrypto_der_cut_nbytes(const uint8_t **data,
    118                                    size_t *dlen,
    119                                    size_t nbytes)
    120 {
    121     *data += nbytes;
    122     *dlen -= nbytes;
    123 }
    124 
    125 static uint8_t qcrypto_der_cut_byte(const uint8_t **data, size_t *dlen)
    126 {
    127     uint8_t val = qcrypto_der_peek_byte(data, dlen);
    128 
    129     qcrypto_der_cut_nbytes(data, dlen, 1);
    130 
    131     return val;
    132 }
    133 
    134 static int qcrypto_der_invoke_callback(QCryptoDERDecodeCb cb, void *ctx,
    135                                        const uint8_t *value, size_t vlen,
    136                                        Error **errp)
    137 {
    138     if (!cb) {
    139         return 0;
    140     }
    141 
    142     return cb(ctx, value, vlen, errp);
    143 }
    144 
    145 static int qcrypto_der_extract_definite_data(const uint8_t **data, size_t *dlen,
    146                                              QCryptoDERDecodeCb cb, void *ctx,
    147                                              Error **errp)
    148 {
    149     const uint8_t *value;
    150     size_t vlen = 0;
    151     uint8_t byte_count = qcrypto_der_cut_byte(data, dlen);
    152 
    153     /* short format of definite-length */
    154     if (!(byte_count & QCRYPTO_DER_SHORT_LEN_MASK)) {
    155         if (byte_count > *dlen) {
    156             error_setg(errp, "Invalid content length: %u", byte_count);
    157             return -1;
    158         }
    159 
    160         value = *data;
    161         vlen = byte_count;
    162         qcrypto_der_cut_nbytes(data, dlen, vlen);
    163 
    164         if (qcrypto_der_invoke_callback(cb, ctx, value, vlen, errp) != 0) {
    165             return -1;
    166         }
    167         return vlen;
    168     }
    169 
    170     /* Ignore highest bit */
    171     byte_count &= ~QCRYPTO_DER_SHORT_LEN_MASK;
    172 
    173     /*
    174      * size_t is enough to store the value of length, although the DER
    175      * encoding standard supports larger length.
    176      */
    177     if (byte_count > sizeof(size_t)) {
    178         error_setg(errp, "Invalid byte count of content length: %u",
    179                    byte_count);
    180         return -1;
    181     }
    182 
    183     if (byte_count > *dlen) {
    184         error_setg(errp, "Invalid content length: %u", byte_count);
    185         return -1;
    186     }
    187     while (byte_count--) {
    188         vlen <<= 8;
    189         vlen += qcrypto_der_cut_byte(data, dlen);
    190     }
    191 
    192     if (vlen > *dlen) {
    193         error_setg(errp, "Invalid content length: %zu", vlen);
    194         return -1;
    195     }
    196 
    197     value = *data;
    198     qcrypto_der_cut_nbytes(data, dlen, vlen);
    199 
    200     if (qcrypto_der_invoke_callback(cb, ctx, value, vlen, errp) != 0) {
    201         return -1;
    202     }
    203     return vlen;
    204 }
    205 
    206 static int qcrypto_der_extract_data(const uint8_t **data, size_t *dlen,
    207                                     QCryptoDERDecodeCb cb, void *ctx,
    208                                     Error **errp)
    209 {
    210     uint8_t val;
    211     if (*dlen < 1) {
    212         error_setg(errp, "Need more data");
    213         return -1;
    214     }
    215     val = qcrypto_der_peek_byte(data, dlen);
    216 
    217     /* must use definite length format */
    218     if (val == QCRYPTO_DER_SHORT_LEN_MASK) {
    219         error_setg(errp, "Only definite length format is allowed");
    220         return -1;
    221     }
    222 
    223     return qcrypto_der_extract_definite_data(data, dlen, cb, ctx, errp);
    224 }
    225 
    226 static int qcrypto_der_decode_tlv(const uint8_t expected_tag,
    227                                   const uint8_t **data, size_t *dlen,
    228                                   QCryptoDERDecodeCb cb,
    229                                   void *ctx, Error **errp)
    230 {
    231     const uint8_t *saved_data = *data;
    232     size_t saved_dlen = *dlen;
    233     uint8_t tag;
    234     int data_length;
    235 
    236     if (*dlen < 1) {
    237         error_setg(errp, "Need more data");
    238         return -1;
    239     }
    240     tag = qcrypto_der_cut_byte(data, dlen);
    241     if (tag != expected_tag) {
    242         error_setg(errp, "Unexpected tag: expected: %u, actual: %u",
    243                    expected_tag, tag);
    244         goto error;
    245     }
    246 
    247     data_length = qcrypto_der_extract_data(data, dlen, cb, ctx, errp);
    248     if (data_length < 0) {
    249         goto error;
    250     }
    251     return data_length;
    252 
    253 error:
    254     *data = saved_data;
    255     *dlen = saved_dlen;
    256     return -1;
    257 }
    258 
    259 int qcrypto_der_decode_int(const uint8_t **data, size_t *dlen,
    260                            QCryptoDERDecodeCb cb, void *ctx, Error **errp)
    261 {
    262     const uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
    263                                         QCRYPTO_DER_TAG_ENC_PRIM,
    264                                         QCRYPTO_DER_TYPE_TAG_INT);
    265     return qcrypto_der_decode_tlv(tag, data, dlen, cb, ctx, errp);
    266 }
    267 
    268 int qcrypto_der_decode_seq(const uint8_t **data, size_t *dlen,
    269                            QCryptoDERDecodeCb cb, void *ctx, Error **errp)
    270 {
    271     uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
    272                                   QCRYPTO_DER_TAG_ENC_CONS,
    273                                   QCRYPTO_DER_TYPE_TAG_SEQ);
    274     return qcrypto_der_decode_tlv(tag, data, dlen, cb, ctx, errp);
    275 }
    276 
    277 int qcrypto_der_decode_octet_str(const uint8_t **data, size_t *dlen,
    278                                  QCryptoDERDecodeCb cb, void *ctx, Error **errp)
    279 {
    280     uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
    281                                   QCRYPTO_DER_TAG_ENC_PRIM,
    282                                   QCRYPTO_DER_TYPE_TAG_OCT_STR);
    283     return qcrypto_der_decode_tlv(tag, data, dlen, cb, ctx, errp);
    284 }
    285 
    286 int qcrypto_der_decode_bit_str(const uint8_t **data, size_t *dlen,
    287                                QCryptoDERDecodeCb cb, void *ctx, Error **errp)
    288 {
    289     uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
    290                                   QCRYPTO_DER_TAG_ENC_PRIM,
    291                                   QCRYPTO_DER_TYPE_TAG_BIT_STR);
    292     return qcrypto_der_decode_tlv(tag, data, dlen, cb, ctx, errp);
    293 }
    294 
    295 int qcrypto_der_decode_oid(const uint8_t **data, size_t *dlen,
    296                            QCryptoDERDecodeCb cb, void *ctx, Error **errp)
    297 {
    298     uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
    299                                   QCRYPTO_DER_TAG_ENC_PRIM,
    300                                   QCRYPTO_DER_TYPE_TAG_OID);
    301     return qcrypto_der_decode_tlv(tag, data, dlen, cb, ctx, errp);
    302 }
    303 
    304 int qcrypto_der_decode_ctx_tag(const uint8_t **data, size_t *dlen, int tag_id,
    305                                QCryptoDERDecodeCb cb, void *ctx, Error **errp)
    306 {
    307     uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_CONT,
    308                                   QCRYPTO_DER_TAG_ENC_CONS,
    309                                   tag_id);
    310     return qcrypto_der_decode_tlv(tag, data, dlen, cb, ctx, errp);
    311 }
    312 
    313 static void qcrypto_der_encode_prim(QCryptoEncodeContext *ctx, uint8_t tag,
    314                                     const uint8_t *data, size_t dlen)
    315 {
    316     QCryptoDerEncodeNode *node = g_new0(QCryptoDerEncodeNode, 1);
    317     size_t nbytes_len;
    318 
    319     node->tag = tag;
    320     node->data = data;
    321     node->dlen = dlen;
    322     node->parent = ctx->current_parent;
    323 
    324     qcrypto_der_encode_length(dlen, NULL, &nbytes_len);
    325     /* 1 byte for Tag, nbyte_len for Length, and dlen for Value */
    326     node->parent->dlen += 1 + nbytes_len + dlen;
    327 
    328     ctx->tail->next = node;
    329     ctx->tail = node;
    330 }
    331 
    332 QCryptoEncodeContext *qcrypto_der_encode_ctx_new(void)
    333 {
    334     QCryptoEncodeContext *ctx = g_new0(QCryptoEncodeContext, 1);
    335     ctx->current_parent = &ctx->root;
    336     ctx->tail = &ctx->root;
    337     return ctx;
    338 }
    339 
    340 static void qcrypto_der_encode_cons_begin(QCryptoEncodeContext *ctx,
    341                                           uint8_t tag)
    342 {
    343     QCryptoDerEncodeNode *node = g_new0(QCryptoDerEncodeNode, 1);
    344 
    345     node->tag = tag;
    346     node->parent = ctx->current_parent;
    347     ctx->current_parent = node;
    348     ctx->tail->next = node;
    349     ctx->tail = node;
    350 }
    351 
    352 static void qcrypto_der_encode_cons_end(QCryptoEncodeContext *ctx)
    353 {
    354     QCryptoDerEncodeNode *cons_node = ctx->current_parent;
    355     size_t nbytes_len;
    356 
    357     qcrypto_der_encode_length(cons_node->dlen, NULL, &nbytes_len);
    358     /* 1 byte for Tag, nbyte_len for Length, and dlen for Value */
    359     cons_node->parent->dlen += 1 + nbytes_len + cons_node->dlen;
    360     ctx->current_parent = cons_node->parent;
    361 }
    362 
    363 void qcrypto_der_encode_seq_begin(QCryptoEncodeContext *ctx)
    364 {
    365     uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
    366                                   QCRYPTO_DER_TAG_ENC_CONS,
    367                                   QCRYPTO_DER_TYPE_TAG_SEQ);
    368     qcrypto_der_encode_cons_begin(ctx, tag);
    369 }
    370 
    371 void qcrypto_der_encode_seq_end(QCryptoEncodeContext *ctx)
    372 {
    373     qcrypto_der_encode_cons_end(ctx);
    374 }
    375 
    376 void qcrypto_der_encode_oid(QCryptoEncodeContext *ctx,
    377                             const uint8_t *src, size_t src_len)
    378 {
    379     uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
    380                                   QCRYPTO_DER_TAG_ENC_PRIM,
    381                                   QCRYPTO_DER_TYPE_TAG_OID);
    382     qcrypto_der_encode_prim(ctx, tag, src, src_len);
    383 }
    384 
    385 void qcrypto_der_encode_int(QCryptoEncodeContext *ctx,
    386                             const uint8_t *src, size_t src_len)
    387 {
    388     uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
    389                                   QCRYPTO_DER_TAG_ENC_PRIM,
    390                                   QCRYPTO_DER_TYPE_TAG_INT);
    391     qcrypto_der_encode_prim(ctx, tag, src, src_len);
    392 }
    393 
    394 void qcrypto_der_encode_null(QCryptoEncodeContext *ctx)
    395 {
    396     uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
    397                                   QCRYPTO_DER_TAG_ENC_PRIM,
    398                                   QCRYPTO_DER_TYPE_TAG_NULL);
    399     qcrypto_der_encode_prim(ctx, tag, NULL, 0);
    400 }
    401 
    402 void qcrypto_der_encode_octet_str(QCryptoEncodeContext *ctx,
    403                                   const uint8_t *src, size_t src_len)
    404 {
    405     uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
    406                                   QCRYPTO_DER_TAG_ENC_PRIM,
    407                                   QCRYPTO_DER_TYPE_TAG_OCT_STR);
    408     qcrypto_der_encode_prim(ctx, tag, src, src_len);
    409 }
    410 
    411 void qcrypto_der_encode_octet_str_begin(QCryptoEncodeContext *ctx)
    412 {
    413     uint8_t tag = QCRYPTO_DER_TAG(QCRYPTO_DER_TAG_CLASS_UNIV,
    414                                   QCRYPTO_DER_TAG_ENC_PRIM,
    415                                   QCRYPTO_DER_TYPE_TAG_OCT_STR);
    416     qcrypto_der_encode_cons_begin(ctx, tag);
    417 }
    418 
    419 void qcrypto_der_encode_octet_str_end(QCryptoEncodeContext *ctx)
    420 {
    421     qcrypto_der_encode_cons_end(ctx);
    422 }
    423 
    424 size_t qcrypto_der_encode_ctx_buffer_len(QCryptoEncodeContext *ctx)
    425 {
    426     return ctx->root.dlen;
    427 }
    428 
    429 void qcrypto_der_encode_ctx_flush_and_free(QCryptoEncodeContext *ctx,
    430                                            uint8_t *dst)
    431 {
    432     QCryptoDerEncodeNode *node, *prev;
    433     size_t len;
    434 
    435     for (prev = &ctx->root;
    436          (node = prev->next) && (prev->next = node->next, 1);) {
    437         /* Tag */
    438         *dst++ = node->tag;
    439 
    440         /* Length */
    441         qcrypto_der_encode_length(node->dlen, dst, &len);
    442         dst += len;
    443 
    444         /* Value */
    445         if (node->data) {
    446             memcpy(dst, node->data, node->dlen);
    447             dst += node->dlen;
    448         }
    449         g_free(node);
    450     }
    451     g_free(ctx);
    452 }