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