1 /* $OpenBSD: asn1basic.c,v 1.4 2022/01/12 07:55:25 tb Exp $ */ 2 /* 3 * Copyright (c) 2017, 2021 Joel Sing <jsing@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <openssl/asn1.h> 19 20 #include <err.h> 21 #include <stdio.h> 22 #include <string.h> 23 24 #include "asn1_locl.h" 25 26 static void 27 hexdump(const unsigned char *buf, size_t len) 28 { 29 size_t i; 30 31 for (i = 1; i <= len; i++) 32 fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); 33 34 fprintf(stderr, "\n"); 35 } 36 37 static int 38 asn1_compare_bytes(const char *label, const unsigned char *d1, int len1, 39 const unsigned char *d2, int len2) 40 { 41 if (len1 != len2) { 42 fprintf(stderr, "FAIL: %s - byte lengths differ " 43 "(%i != %i)\n", label, len1, len2); 44 fprintf(stderr, "Got:\n"); 45 hexdump(d1, len1); 46 fprintf(stderr, "Want:\n"); 47 hexdump(d2, len2); 48 return 0; 49 } 50 if (memcmp(d1, d2, len1) != 0) { 51 fprintf(stderr, "FAIL: %s - bytes differ\n", label); 52 fprintf(stderr, "Got:\n"); 53 hexdump(d1, len1); 54 fprintf(stderr, "Want:\n"); 55 hexdump(d2, len2); 56 return 0; 57 } 58 return 1; 59 } 60 61 const uint8_t asn1_bit_string_primitive[] = { 62 0x03, 0x07, 63 0x04, 0x0a, 0x3b, 0x5f, 0x29, 0x1c, 0xd0, 64 }; 65 66 static int 67 asn1_bit_string_test(void) 68 { 69 uint8_t bs[] = {0x0a, 0x3b, 0x5f, 0x29, 0x1c, 0xd0}; 70 ASN1_BIT_STRING *abs; 71 uint8_t *p = NULL, *pp; 72 const uint8_t *q; 73 int bit, i, len; 74 int failed = 1; 75 76 if ((abs = ASN1_BIT_STRING_new()) == NULL) { 77 fprintf(stderr, "FAIL: ASN1_BIT_STRING_new() == NULL\n"); 78 goto failed; 79 } 80 if (!ASN1_BIT_STRING_set(abs, bs, sizeof(bs))) { 81 fprintf(stderr, "FAIL: failed to set bit string\n"); 82 goto failed; 83 } 84 85 if ((len = i2d_ASN1_BIT_STRING(abs, NULL)) < 0) { 86 fprintf(stderr, "FAIL: i2d_ASN1_BIT_STRING with NULL\n"); 87 goto failed; 88 } 89 if ((p = malloc(len)) == NULL) 90 errx(1, "malloc"); 91 memset(p, 0xbd, len); 92 pp = p; 93 if ((i2d_ASN1_BIT_STRING(abs, &pp)) != len) { 94 fprintf(stderr, "FAIL: i2d_ASN1_BIT_STRING\n"); 95 goto failed; 96 } 97 98 if (!asn1_compare_bytes("BIT_STRING", p, len, asn1_bit_string_primitive, 99 sizeof(asn1_bit_string_primitive))) 100 goto failed; 101 102 /* Test primitive decoding. */ 103 q = p; 104 if (d2i_ASN1_BIT_STRING(&abs, &q, len) == NULL) { 105 fprintf(stderr, "FAIL: d2i_ASN1_BIT_STRING primitive\n"); 106 goto failed; 107 } 108 if (!asn1_compare_bytes("BIT_STRING primitive data", abs->data, abs->length, 109 bs, sizeof(bs))) 110 goto failed; 111 112 /* Test ASN1_BIT_STRING_get_bit(). */ 113 for (i = 0; i < ((int)sizeof(bs) * 8); i++) { 114 bit = (bs[i / 8] >> (7 - i % 8)) & 1; 115 116 if (ASN1_BIT_STRING_get_bit(abs, i) != bit) { 117 fprintf(stderr, "FAIL: ASN1_BIT_STRING_get_bit(_, %d) " 118 "= %d, want %d\n", i, 119 ASN1_BIT_STRING_get_bit(abs, i), bit); 120 goto failed; 121 } 122 } 123 124 /* Test ASN1_BIT_STRING_set_bit(). */ 125 for (i = 0; i < ((int)sizeof(bs) * 8); i++) { 126 if (!ASN1_BIT_STRING_set_bit(abs, i, 1)) { 127 fprintf(stderr, "FAIL: ASN1_BIT_STRING_set_bit 1\n"); 128 goto failed; 129 } 130 } 131 for (i = ((int)sizeof(bs) * 8) - 1; i >= 0; i--) { 132 bit = (bs[i / 8] >> (7 - i % 8)) & 1; 133 if (bit == 1) 134 continue; 135 if (!ASN1_BIT_STRING_set_bit(abs, i, 0)) { 136 fprintf(stderr, "FAIL: ASN1_BIT_STRING_set_bit\n"); 137 goto failed; 138 } 139 } 140 141 if ((i2d_ASN1_BIT_STRING(abs, NULL)) != len) { 142 fprintf(stderr, "FAIL: i2d_ASN1_BIT_STRING\n"); 143 goto failed; 144 } 145 146 memset(p, 0xbd, len); 147 pp = p; 148 if ((i2d_ASN1_BIT_STRING(abs, &pp)) != len) { 149 fprintf(stderr, "FAIL: i2d_ASN1_BIT_STRING\n"); 150 goto failed; 151 } 152 153 if (!asn1_compare_bytes("BIT_STRING set", p, len, asn1_bit_string_primitive, 154 sizeof(asn1_bit_string_primitive))) 155 goto failed; 156 157 failed = 0; 158 159 failed: 160 ASN1_BIT_STRING_free(abs); 161 free(p); 162 163 return failed; 164 } 165 166 const uint8_t asn1_boolean_false[] = { 167 0x01, 0x01, 0x00, 168 }; 169 const uint8_t asn1_boolean_true[] = { 170 0x01, 0x01, 0x01, 171 }; 172 173 static int 174 asn1_boolean_test(void) 175 { 176 uint8_t *p = NULL, *pp; 177 const uint8_t *q; 178 int len; 179 int failed = 1; 180 181 if ((len = i2d_ASN1_BOOLEAN(0, NULL)) < 0) { 182 fprintf(stderr, "FAIL: i2d_ASN1_BOOLEAN false with NULL\n"); 183 goto failed; 184 } 185 if ((p = malloc(len)) == NULL) 186 errx(1, "calloc"); 187 memset(p, 0xbd, len); 188 pp = p; 189 if ((i2d_ASN1_BOOLEAN(0, &pp)) != len) { 190 fprintf(stderr, "FAIL: i2d_ASN1_BOOLEAN false\n"); 191 goto failed; 192 } 193 194 if (!asn1_compare_bytes("BOOLEAN false", p, len, asn1_boolean_false, 195 sizeof(asn1_boolean_false))) 196 goto failed; 197 198 q = p; 199 if (d2i_ASN1_BOOLEAN(NULL, &q, len) != 0) { 200 fprintf(stderr, "FAIL: BOOLEAN false did not decode to 0\n"); 201 goto failed; 202 } 203 204 free(p); 205 p = NULL; 206 207 if ((len = i2d_ASN1_BOOLEAN(1, NULL)) < 0) { 208 fprintf(stderr, "FAIL: i2d_ASN1_BOOLEAN true with NULL\n"); 209 goto failed; 210 } 211 if ((p = calloc(1, len)) == NULL) 212 errx(1, "calloc"); 213 pp = p; 214 if ((i2d_ASN1_BOOLEAN(1, &pp)) != len) { 215 fprintf(stderr, "FAIL: i2d_ASN1_BOOLEAN true\n"); 216 goto failed; 217 } 218 219 if (!asn1_compare_bytes("BOOLEAN true", p, len, asn1_boolean_true, 220 sizeof(asn1_boolean_true))) 221 goto failed; 222 223 q = p; 224 if (d2i_ASN1_BOOLEAN(NULL, &q, len) != 1) { 225 fprintf(stderr, "FAIL: BOOLEAN true did not decode to 1\n"); 226 goto failed; 227 } 228 229 failed = 0; 230 231 failed: 232 free(p); 233 234 return failed; 235 } 236 237 int 238 main(int argc, char **argv) 239 { 240 int failed = 0; 241 242 failed |= asn1_bit_string_test(); 243 failed |= asn1_boolean_test(); 244 245 return (failed); 246 } 247