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 enum QCryptoDERTypeTag { 26 QCRYPTO_DER_TYPE_TAG_BOOL = 0x1, 27 QCRYPTO_DER_TYPE_TAG_INT = 0x2, 28 QCRYPTO_DER_TYPE_TAG_BIT_STR = 0x3, 29 QCRYPTO_DER_TYPE_TAG_OCT_STR = 0x4, 30 QCRYPTO_DER_TYPE_TAG_OCT_NULL = 0x5, 31 QCRYPTO_DER_TYPE_TAG_OCT_OID = 0x6, 32 QCRYPTO_DER_TYPE_TAG_SEQ = 0x10, 33 QCRYPTO_DER_TYPE_TAG_SET = 0x11, 34 }; 35 36 #define QCRYPTO_DER_CONSTRUCTED_MASK 0x20 37 #define QCRYPTO_DER_SHORT_LEN_MASK 0x80 38 39 static uint8_t qcrypto_der_peek_byte(const uint8_t **data, size_t *dlen) 40 { 41 return **data; 42 } 43 44 static void qcrypto_der_cut_nbytes(const uint8_t **data, 45 size_t *dlen, 46 size_t nbytes) 47 { 48 *data += nbytes; 49 *dlen -= nbytes; 50 } 51 52 static uint8_t qcrypto_der_cut_byte(const uint8_t **data, size_t *dlen) 53 { 54 uint8_t val = qcrypto_der_peek_byte(data, dlen); 55 56 qcrypto_der_cut_nbytes(data, dlen, 1); 57 58 return val; 59 } 60 61 static int qcrypto_der_invoke_callback(QCryptoDERDecodeCb cb, void *ctx, 62 const uint8_t *value, size_t vlen, 63 Error **errp) 64 { 65 if (!cb) { 66 return 0; 67 } 68 69 return cb(ctx, value, vlen, errp); 70 } 71 72 static int qcrypto_der_extract_definite_data(const uint8_t **data, size_t *dlen, 73 QCryptoDERDecodeCb cb, void *ctx, 74 Error **errp) 75 { 76 const uint8_t *value; 77 size_t vlen = 0; 78 uint8_t byte_count = qcrypto_der_cut_byte(data, dlen); 79 80 /* short format of definite-length */ 81 if (!(byte_count & QCRYPTO_DER_SHORT_LEN_MASK)) { 82 if (byte_count > *dlen) { 83 error_setg(errp, "Invalid content length: %u", byte_count); 84 return -1; 85 } 86 87 value = *data; 88 vlen = byte_count; 89 qcrypto_der_cut_nbytes(data, dlen, vlen); 90 91 if (qcrypto_der_invoke_callback(cb, ctx, value, vlen, errp) != 0) { 92 return -1; 93 } 94 return vlen; 95 } 96 97 /* Ignore highest bit */ 98 byte_count &= ~QCRYPTO_DER_SHORT_LEN_MASK; 99 100 /* 101 * size_t is enough to store the value of length, although the DER 102 * encoding standard supports larger length. 103 */ 104 if (byte_count > sizeof(size_t)) { 105 error_setg(errp, "Invalid byte count of content length: %u", 106 byte_count); 107 return -1; 108 } 109 110 if (byte_count > *dlen) { 111 error_setg(errp, "Invalid content length: %u", byte_count); 112 return -1; 113 } 114 while (byte_count--) { 115 vlen <<= 8; 116 vlen += qcrypto_der_cut_byte(data, dlen); 117 } 118 119 if (vlen > *dlen) { 120 error_setg(errp, "Invalid content length: %zu", vlen); 121 return -1; 122 } 123 124 value = *data; 125 qcrypto_der_cut_nbytes(data, dlen, vlen); 126 127 if (qcrypto_der_invoke_callback(cb, ctx, value, vlen, errp) != 0) { 128 return -1; 129 } 130 return vlen; 131 } 132 133 static int qcrypto_der_extract_data(const uint8_t **data, size_t *dlen, 134 QCryptoDERDecodeCb cb, void *ctx, 135 Error **errp) 136 { 137 uint8_t val; 138 if (*dlen < 1) { 139 error_setg(errp, "Need more data"); 140 return -1; 141 } 142 val = qcrypto_der_peek_byte(data, dlen); 143 144 /* must use definite length format */ 145 if (val == QCRYPTO_DER_SHORT_LEN_MASK) { 146 error_setg(errp, "Only definite length format is allowed"); 147 return -1; 148 } 149 150 return qcrypto_der_extract_definite_data(data, dlen, cb, ctx, errp); 151 } 152 153 int qcrypto_der_decode_int(const uint8_t **data, size_t *dlen, 154 QCryptoDERDecodeCb cb, void *ctx, Error **errp) 155 { 156 uint8_t tag; 157 if (*dlen < 1) { 158 error_setg(errp, "Need more data"); 159 return -1; 160 } 161 tag = qcrypto_der_cut_byte(data, dlen); 162 163 /* INTEGER must encoded in primitive-form */ 164 if (tag != QCRYPTO_DER_TYPE_TAG_INT) { 165 error_setg(errp, "Invalid integer type tag: %u", tag); 166 return -1; 167 } 168 169 return qcrypto_der_extract_data(data, dlen, cb, ctx, errp); 170 } 171 172 int qcrypto_der_decode_seq(const uint8_t **data, size_t *dlen, 173 QCryptoDERDecodeCb cb, void *ctx, Error **errp) 174 { 175 uint8_t tag; 176 if (*dlen < 1) { 177 error_setg(errp, "Need more data"); 178 return -1; 179 } 180 tag = qcrypto_der_cut_byte(data, dlen); 181 182 /* SEQUENCE must use constructed form */ 183 if (tag != (QCRYPTO_DER_TYPE_TAG_SEQ | QCRYPTO_DER_CONSTRUCTED_MASK)) { 184 error_setg(errp, "Invalid type sequence tag: %u", tag); 185 return -1; 186 } 187 188 return qcrypto_der_extract_data(data, dlen, cb, ctx, errp); 189 } 190