1 /* 2 * Copyright 2020-2025 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 /* 11 * This is a decoder that's completely internal to the 'file:' store 12 * implementation. Only code in file_store.c know about this one. Because 13 * of this close relationship, we can cut certain corners, such as making 14 * assumptions about the "provider context", which is currently simply the 15 * provider context that the file_store.c code operates within. 16 * 17 * All this does is to read known binary encodings (currently: DER, MSBLOB, 18 * PVK) from the input if it can, and passes it on to the data callback as 19 * an object abstraction, leaving it to the callback to figure out what it 20 * actually is. 21 * 22 * This MUST be made the last decoder in a chain, leaving it to other more 23 * specialized decoders to recognise and process their stuff first. 24 */ 25 26 #include <openssl/core_dispatch.h> 27 #include <openssl/core_names.h> 28 #include <openssl/core_object.h> 29 #include <openssl/bio.h> 30 #include <openssl/buffer.h> 31 #include <openssl/err.h> 32 #include <openssl/asn1err.h> 33 #include <openssl/params.h> 34 #include "internal/asn1.h" 35 #include "internal/sizes.h" 36 #include "crypto/pem.h" /* For internal PVK and "blob" headers */ 37 #include "prov/bio.h" 38 #include "file_store_local.h" 39 40 /* 41 * newctx and freectx are not strictly necessary. However, the method creator, 42 * ossl_decoder_from_algorithm(), demands that they exist, so we make sure to 43 * oblige. 44 */ 45 46 static OSSL_FUNC_decoder_newctx_fn any2obj_newctx; 47 static OSSL_FUNC_decoder_freectx_fn any2obj_freectx; 48 49 struct any2obj_ctx_st { 50 PROV_CTX *provctx; 51 char data_structure[OSSL_MAX_CODEC_STRUCT_SIZE]; 52 }; 53 54 static void *any2obj_newctx(void *provctx) 55 { 56 struct any2obj_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx)); 57 58 if (ctx != NULL) 59 ctx->provctx = provctx; 60 return ctx; 61 } 62 63 static void any2obj_freectx(void *ctx) 64 { 65 OPENSSL_free(ctx); 66 } 67 68 static int any2obj_set_ctx_params(void *vctx, const OSSL_PARAM params[]) 69 { 70 struct any2obj_ctx_st *ctx = vctx; 71 const OSSL_PARAM *p; 72 char *str; 73 74 p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_DATA_STRUCTURE); 75 str = ctx->data_structure; 76 if (p != NULL 77 && !OSSL_PARAM_get_utf8_string(p, &str, sizeof(ctx->data_structure))) 78 return 0; 79 80 return 1; 81 } 82 83 static const OSSL_PARAM *any2obj_settable_ctx_params(ossl_unused void *provctx) 84 { 85 static const OSSL_PARAM settables[] = { 86 OSSL_PARAM_utf8_string(OSSL_OBJECT_PARAM_DATA_STRUCTURE, NULL, 0), 87 OSSL_PARAM_END 88 }; 89 return settables; 90 } 91 92 static int any2obj_decode_final(void *vctx, int objtype, const char *input_type, 93 const char *data_type, BUF_MEM *mem, 94 OSSL_CALLBACK *data_cb, void *data_cbarg) 95 { 96 struct any2obj_ctx_st *ctx = vctx; 97 /* 98 * 1 indicates that we successfully decoded something, or not at all. 99 * Ending up "empty handed" is not an error. 100 */ 101 int ok = 1; 102 103 if (mem != NULL) { 104 OSSL_PARAM params[6], *p = params; 105 106 if (data_type != NULL) 107 *p++ = OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE, 108 (char *)data_type, 0); 109 if (input_type != NULL) 110 *p++ = OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_INPUT_TYPE, 111 (char *)input_type, 0); 112 if (*ctx->data_structure != '\0') 113 *p++ = OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_STRUCTURE, 114 (char *)ctx->data_structure, 0); 115 *p++ = OSSL_PARAM_construct_int(OSSL_OBJECT_PARAM_TYPE, &objtype); 116 *p++ = OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_DATA, 117 mem->data, mem->length); 118 *p = OSSL_PARAM_construct_end(); 119 120 ok = data_cb(params, data_cbarg); 121 BUF_MEM_free(mem); 122 } 123 return ok; 124 } 125 126 static OSSL_FUNC_decoder_decode_fn der2obj_decode; 127 static int der2obj_decode(void *vctx, OSSL_CORE_BIO *cin, int selection, 128 OSSL_CALLBACK *data_cb, void *data_cbarg, 129 OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) 130 { 131 struct any2obj_ctx_st *ctx = vctx; 132 BIO *in = ossl_bio_new_from_core_bio(ctx->provctx, cin); 133 BUF_MEM *mem = NULL; 134 int ok; 135 136 if (in == NULL) 137 return 0; 138 139 ERR_set_mark(); 140 ok = (asn1_d2i_read_bio(in, &mem) >= 0); 141 ERR_pop_to_mark(); 142 if (!ok && mem != NULL) { 143 BUF_MEM_free(mem); 144 mem = NULL; 145 } 146 BIO_free(in); 147 148 /* any2obj_decode_final() frees |mem| for us */ 149 return any2obj_decode_final(ctx, OSSL_OBJECT_UNKNOWN, NULL, NULL, mem, 150 data_cb, data_cbarg); 151 } 152 153 static OSSL_FUNC_decoder_decode_fn msblob2obj_decode; 154 static int msblob2obj_decode(void *vctx, OSSL_CORE_BIO *cin, int selection, 155 OSSL_CALLBACK *data_cb, void *data_cbarg, 156 OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) 157 { 158 struct any2obj_ctx_st *ctx = vctx; 159 BIO *in = ossl_bio_new_from_core_bio(ctx->provctx, cin); 160 BUF_MEM *mem = NULL; 161 size_t mem_len = 0, mem_want; 162 const unsigned char *p; 163 unsigned int bitlen, magic; 164 int isdss = -1; 165 int ispub = -1; 166 int ok = 0; 167 168 if (in == NULL) 169 goto err; 170 171 mem_want = 16; /* The size of the MSBLOB header */ 172 if ((mem = BUF_MEM_new()) == NULL 173 || !BUF_MEM_grow(mem, mem_want)) { 174 ERR_raise(ERR_LIB_PEM, ERR_R_BUF_LIB); 175 goto err; 176 } 177 178 ERR_set_mark(); 179 ok = BIO_read(in, &mem->data[0], mem_want) == (int)mem_want; 180 mem_len += mem_want; 181 ERR_pop_to_mark(); 182 if (!ok) 183 goto next; 184 185 ERR_set_mark(); 186 p = (unsigned char *)&mem->data[0]; 187 ok = ossl_do_blob_header(&p, 16, &magic, &bitlen, &isdss, &ispub) > 0; 188 ERR_pop_to_mark(); 189 if (!ok) 190 goto next; 191 192 ok = 0; 193 mem_want = ossl_blob_length(bitlen, isdss, ispub); 194 if (!BUF_MEM_grow(mem, mem_len + mem_want)) { 195 ERR_raise(ERR_LIB_PEM, ERR_R_BUF_LIB); 196 goto err; 197 } 198 199 ERR_set_mark(); 200 ok = BIO_read(in, &mem->data[mem_len], mem_want) == (int)mem_want; 201 mem_len += mem_want; 202 ERR_pop_to_mark(); 203 204 next: 205 /* Free resources we no longer need. */ 206 BIO_free(in); 207 if (!ok && mem != NULL) { 208 BUF_MEM_free(mem); 209 mem = NULL; 210 } 211 212 /* any2obj_decode_final() frees |mem| for us */ 213 return any2obj_decode_final(ctx, OSSL_OBJECT_PKEY, "msblob", 214 isdss ? "DSA" : "RSA", mem, 215 data_cb, data_cbarg); 216 217 err: 218 BIO_free(in); 219 BUF_MEM_free(mem); 220 return 0; 221 } 222 223 static OSSL_FUNC_decoder_decode_fn pvk2obj_decode; 224 static int pvk2obj_decode(void *vctx, OSSL_CORE_BIO *cin, int selection, 225 OSSL_CALLBACK *data_cb, void *data_cbarg, 226 OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) 227 { 228 struct any2obj_ctx_st *ctx = vctx; 229 BIO *in = ossl_bio_new_from_core_bio(ctx->provctx, cin); 230 BUF_MEM *mem = NULL; 231 size_t mem_len = 0, mem_want; 232 const unsigned char *p; 233 unsigned int saltlen, keylen; 234 int ok = 0, isdss = -1; 235 236 if (in == NULL) 237 goto err; 238 239 mem_want = 24; /* The size of the PVK header */ 240 if ((mem = BUF_MEM_new()) == NULL 241 || !BUF_MEM_grow(mem, mem_want)) { 242 ERR_raise(ERR_LIB_PEM, ERR_R_BUF_LIB); 243 goto err; 244 } 245 246 ERR_set_mark(); 247 ok = BIO_read(in, &mem->data[0], mem_want) == (int)mem_want; 248 mem_len += mem_want; 249 ERR_pop_to_mark(); 250 if (!ok) 251 goto next; 252 253 ERR_set_mark(); 254 p = (unsigned char *)&mem->data[0]; 255 ok = ossl_do_PVK_header(&p, 24, 0, &isdss, &saltlen, &keylen) > 0; 256 ERR_pop_to_mark(); 257 if (!ok) 258 goto next; 259 260 ok = 0; 261 mem_want = saltlen + keylen; 262 if (!BUF_MEM_grow(mem, mem_len + mem_want)) { 263 ERR_raise(ERR_LIB_PEM, ERR_R_BUF_LIB); 264 goto err; 265 } 266 267 ERR_set_mark(); 268 ok = BIO_read(in, &mem->data[mem_len], mem_want) == (int)mem_want; 269 mem_len += mem_want; 270 ERR_pop_to_mark(); 271 272 next: 273 /* Free resources we no longer need. */ 274 BIO_free(in); 275 if (!ok && mem != NULL) { 276 BUF_MEM_free(mem); 277 mem = NULL; 278 } 279 280 /* any2obj_decode_final() frees |mem| for us */ 281 return any2obj_decode_final(ctx, OSSL_OBJECT_PKEY, "pvk", 282 ok ? (isdss ? "DSA" : "RSA") : NULL, mem, 283 data_cb, data_cbarg); 284 285 err: 286 BIO_free(in); 287 BUF_MEM_free(mem); 288 return 0; 289 } 290 291 #define MAKE_DECODER(fromtype, objtype) \ 292 static const OSSL_DISPATCH fromtype##_to_obj_decoder_functions[] = { \ 293 { OSSL_FUNC_DECODER_NEWCTX, (void (*)(void))any2obj_newctx }, \ 294 { OSSL_FUNC_DECODER_FREECTX, (void (*)(void))any2obj_freectx }, \ 295 { OSSL_FUNC_DECODER_DECODE, (void (*)(void))fromtype##2obj_decode }, \ 296 { OSSL_FUNC_DECODER_SETTABLE_CTX_PARAMS, \ 297 (void (*)(void))any2obj_settable_ctx_params }, \ 298 { OSSL_FUNC_DECODER_SET_CTX_PARAMS, \ 299 (void (*)(void))any2obj_set_ctx_params }, \ 300 OSSL_DISPATCH_END \ 301 } 302 303 MAKE_DECODER(der, OSSL_OBJECT_UNKNOWN); 304 MAKE_DECODER(msblob, OSSL_OBJECT_PKEY); 305 MAKE_DECODER(pvk, OSSL_OBJECT_PKEY); 306 307 const OSSL_ALGORITHM ossl_any_to_obj_algorithm[] = { 308 { "obj", "input=DER", der_to_obj_decoder_functions }, 309 { "obj", "input=MSBLOB", msblob_to_obj_decoder_functions }, 310 { "obj", "input=PVK", pvk_to_obj_decoder_functions }, 311 { 312 NULL, 313 } 314 }; 315