1 /* 2 * Copyright 2017-2024 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #include <stdio.h> 11 #include <string.h> 12 13 #include <openssl/rand.h> 14 #include <openssl/asn1.h> 15 #include <openssl/asn1t.h> 16 #include <openssl/obj_mac.h> 17 #include "internal/numbers.h" 18 #include "testutil.h" 19 20 #ifdef __GNUC__ 21 # pragma GCC diagnostic ignored "-Wunused-function" 22 #endif 23 #ifdef __clang__ 24 # pragma clang diagnostic ignored "-Wunused-function" 25 #endif 26 27 /* Badly coded ASN.1 INTEGER zero wrapped in a sequence */ 28 static unsigned char t_invalid_zero[] = { 29 0x30, 0x02, /* SEQUENCE tag + length */ 30 0x02, 0x00 /* INTEGER tag + length */ 31 }; 32 33 #ifndef OPENSSL_NO_DEPRECATED_3_0 34 /* LONG case ************************************************************* */ 35 36 typedef struct { 37 long test_long; 38 } ASN1_LONG_DATA; 39 40 ASN1_SEQUENCE(ASN1_LONG_DATA) = { 41 ASN1_EMBED(ASN1_LONG_DATA, test_long, LONG), 42 } static_ASN1_SEQUENCE_END(ASN1_LONG_DATA) 43 44 IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(ASN1_LONG_DATA) 45 IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(ASN1_LONG_DATA) 46 47 static int test_long(void) 48 { 49 const unsigned char *p = t_invalid_zero; 50 ASN1_LONG_DATA *dectst = 51 d2i_ASN1_LONG_DATA(NULL, &p, sizeof(t_invalid_zero)); 52 53 if (dectst == NULL) 54 return 0; /* Fail */ 55 56 ASN1_LONG_DATA_free(dectst); 57 return 1; 58 } 59 #endif 60 61 /* INT32 case ************************************************************* */ 62 63 typedef struct { 64 int32_t test_int32; 65 } ASN1_INT32_DATA; 66 67 ASN1_SEQUENCE(ASN1_INT32_DATA) = { 68 ASN1_EMBED(ASN1_INT32_DATA, test_int32, INT32), 69 } static_ASN1_SEQUENCE_END(ASN1_INT32_DATA) 70 71 IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(ASN1_INT32_DATA) 72 IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(ASN1_INT32_DATA) 73 74 static int test_int32(void) 75 { 76 const unsigned char *p = t_invalid_zero; 77 ASN1_INT32_DATA *dectst = 78 d2i_ASN1_INT32_DATA(NULL, &p, sizeof(t_invalid_zero)); 79 80 if (dectst == NULL) 81 return 0; /* Fail */ 82 83 ASN1_INT32_DATA_free(dectst); 84 return 1; 85 } 86 87 /* UINT32 case ************************************************************* */ 88 89 typedef struct { 90 uint32_t test_uint32; 91 } ASN1_UINT32_DATA; 92 93 ASN1_SEQUENCE(ASN1_UINT32_DATA) = { 94 ASN1_EMBED(ASN1_UINT32_DATA, test_uint32, UINT32), 95 } static_ASN1_SEQUENCE_END(ASN1_UINT32_DATA) 96 97 IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(ASN1_UINT32_DATA) 98 IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(ASN1_UINT32_DATA) 99 100 static int test_uint32(void) 101 { 102 const unsigned char *p = t_invalid_zero; 103 ASN1_UINT32_DATA *dectst = 104 d2i_ASN1_UINT32_DATA(NULL, &p, sizeof(t_invalid_zero)); 105 106 if (dectst == NULL) 107 return 0; /* Fail */ 108 109 ASN1_UINT32_DATA_free(dectst); 110 return 1; 111 } 112 113 /* INT64 case ************************************************************* */ 114 115 typedef struct { 116 int64_t test_int64; 117 } ASN1_INT64_DATA; 118 119 ASN1_SEQUENCE(ASN1_INT64_DATA) = { 120 ASN1_EMBED(ASN1_INT64_DATA, test_int64, INT64), 121 } static_ASN1_SEQUENCE_END(ASN1_INT64_DATA) 122 123 IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(ASN1_INT64_DATA) 124 IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(ASN1_INT64_DATA) 125 126 static int test_int64(void) 127 { 128 const unsigned char *p = t_invalid_zero; 129 ASN1_INT64_DATA *dectst = 130 d2i_ASN1_INT64_DATA(NULL, &p, sizeof(t_invalid_zero)); 131 132 if (dectst == NULL) 133 return 0; /* Fail */ 134 135 ASN1_INT64_DATA_free(dectst); 136 return 1; 137 } 138 139 /* UINT64 case ************************************************************* */ 140 141 typedef struct { 142 uint64_t test_uint64; 143 } ASN1_UINT64_DATA; 144 145 ASN1_SEQUENCE(ASN1_UINT64_DATA) = { 146 ASN1_EMBED(ASN1_UINT64_DATA, test_uint64, UINT64), 147 } static_ASN1_SEQUENCE_END(ASN1_UINT64_DATA) 148 149 IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(ASN1_UINT64_DATA) 150 IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(ASN1_UINT64_DATA) 151 152 static int test_uint64(void) 153 { 154 const unsigned char *p = t_invalid_zero; 155 ASN1_UINT64_DATA *dectst = 156 d2i_ASN1_UINT64_DATA(NULL, &p, sizeof(t_invalid_zero)); 157 158 if (dectst == NULL) 159 return 0; /* Fail */ 160 161 ASN1_UINT64_DATA_free(dectst); 162 return 1; 163 } 164 165 /* GeneralizedTime underflow *********************************************** */ 166 167 static int test_gentime(void) 168 { 169 /* Underflowing GeneralizedTime 161208193400Z (YYMMDDHHMMSSZ) */ 170 const unsigned char der[] = { 171 0x18, 0x0d, 0x31, 0x36, 0x31, 0x32, 0x30, 0x38, 0x31, 172 0x39, 0x33, 0x34, 0x30, 0x30, 0x5a, 173 }; 174 const unsigned char *p; 175 int der_len, rc = 1; 176 ASN1_GENERALIZEDTIME *gentime; 177 178 p = der; 179 der_len = sizeof(der); 180 gentime = d2i_ASN1_GENERALIZEDTIME(NULL, &p, der_len); 181 182 if (!TEST_ptr_null(gentime)) 183 rc = 0; /* fail */ 184 185 ASN1_GENERALIZEDTIME_free(gentime); 186 return rc; 187 } 188 189 /* UTCTime underflow ******************************************************* */ 190 191 static int test_utctime(void) 192 { 193 /* Underflowing UTCTime 0205104700Z (MMDDHHMMSSZ) */ 194 const unsigned char der[] = { 195 0x17, 0x0b, 0x30, 0x32, 0x30, 0x35, 0x31, 0x30, 196 0x34, 0x37, 0x30, 0x30, 0x5a, 197 }; 198 const unsigned char *p; 199 int der_len, rc = 1; 200 ASN1_UTCTIME *utctime; 201 202 p = der; 203 der_len = sizeof(der); 204 utctime = d2i_ASN1_UTCTIME(NULL, &p, der_len); 205 206 if (!TEST_ptr_null(utctime)) 207 rc = 0; /* fail */ 208 209 ASN1_UTCTIME_free(utctime); 210 return rc; 211 } 212 213 /* Invalid template ******************************************************** */ 214 215 typedef struct { 216 ASN1_STRING *invalidDirString; 217 } INVALIDTEMPLATE; 218 219 ASN1_SEQUENCE(INVALIDTEMPLATE) = { 220 /* 221 * DirectoryString is a CHOICE type so it must use explicit tagging - 222 * but we deliberately use implicit here, which makes this template invalid. 223 */ 224 ASN1_IMP(INVALIDTEMPLATE, invalidDirString, DIRECTORYSTRING, 12) 225 } static_ASN1_SEQUENCE_END(INVALIDTEMPLATE) 226 227 IMPLEMENT_STATIC_ASN1_ENCODE_FUNCTIONS(INVALIDTEMPLATE) 228 IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(INVALIDTEMPLATE) 229 230 /* Empty sequence for invalid template test */ 231 static unsigned char t_invalid_template[] = { 232 0x30, 0x03, /* SEQUENCE tag + length */ 233 0x0c, 0x01, 0x41 /* UTF8String, length 1, "A" */ 234 }; 235 236 static int test_invalid_template(void) 237 { 238 const unsigned char *p = t_invalid_template; 239 INVALIDTEMPLATE *tmp = d2i_INVALIDTEMPLATE(NULL, &p, 240 sizeof(t_invalid_template)); 241 242 /* We expect a NULL pointer return */ 243 if (TEST_ptr_null(tmp)) 244 return 1; 245 246 INVALIDTEMPLATE_free(tmp); 247 return 0; 248 } 249 250 static int test_reuse_asn1_object(void) 251 { 252 static unsigned char cn_der[] = { 0x06, 0x03, 0x55, 0x04, 0x06 }; 253 static unsigned char oid_der[] = { 254 0x06, 0x06, 0x2a, 0x03, 0x04, 0x05, 0x06, 0x07 255 }; 256 int ret = 0; 257 ASN1_OBJECT *obj; 258 unsigned char const *p = oid_der; 259 260 /* Create an object that owns dynamically allocated 'sn' and 'ln' fields */ 261 262 if (!TEST_ptr(obj = ASN1_OBJECT_create(NID_undef, cn_der, sizeof(cn_der), 263 "C", "countryName"))) 264 goto err; 265 /* reuse obj - this should not leak sn and ln */ 266 if (!TEST_ptr(d2i_ASN1_OBJECT(&obj, &p, sizeof(oid_der)))) 267 goto err; 268 ret = 1; 269 err: 270 ASN1_OBJECT_free(obj); 271 return ret; 272 } 273 274 int setup_tests(void) 275 { 276 #ifndef OPENSSL_NO_DEPRECATED_3_0 277 ADD_TEST(test_long); 278 #endif 279 ADD_TEST(test_int32); 280 ADD_TEST(test_uint32); 281 ADD_TEST(test_int64); 282 ADD_TEST(test_uint64); 283 ADD_TEST(test_gentime); 284 ADD_TEST(test_utctime); 285 ADD_TEST(test_invalid_template); 286 ADD_TEST(test_reuse_asn1_object); 287 return 1; 288 } 289