1 /* 2 * Copyright 2020-2021 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 "crypto/pem.h" /* For internal PVK and "blob" headers */ 36 #include "prov/bio.h" 37 #include "file_store_local.h" 38 39 /* 40 * newctx and freectx are not strictly necessary. However, the method creator, 41 * ossl_decoder_from_algorithm(), demands that they exist, so we make sure to 42 * oblige. 43 */ 44 45 static OSSL_FUNC_decoder_newctx_fn any2obj_newctx; 46 static OSSL_FUNC_decoder_freectx_fn any2obj_freectx; 47 48 static void *any2obj_newctx(void *provctx) 49 { 50 return provctx; 51 } 52 53 static void any2obj_freectx(void *vctx) 54 { 55 } 56 57 static int any2obj_decode_final(void *provctx, int objtype, BUF_MEM *mem, 58 OSSL_CALLBACK *data_cb, void *data_cbarg) 59 { 60 /* 61 * 1 indicates that we successfully decoded something, or not at all. 62 * Ending up "empty handed" is not an error. 63 */ 64 int ok = 1; 65 66 if (mem != NULL) { 67 OSSL_PARAM params[3]; 68 69 params[0] = 70 OSSL_PARAM_construct_int(OSSL_OBJECT_PARAM_TYPE, &objtype); 71 params[1] = 72 OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_DATA, 73 mem->data, mem->length); 74 params[2] = OSSL_PARAM_construct_end(); 75 76 ok = data_cb(params, data_cbarg); 77 BUF_MEM_free(mem); 78 } 79 return ok; 80 } 81 82 static OSSL_FUNC_decoder_decode_fn der2obj_decode; 83 static int der2obj_decode(void *provctx, OSSL_CORE_BIO *cin, int selection, 84 OSSL_CALLBACK *data_cb, void *data_cbarg, 85 OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) 86 { 87 BIO *in = ossl_bio_new_from_core_bio(provctx, cin); 88 BUF_MEM *mem = NULL; 89 int ok; 90 91 if (in == NULL) 92 return 0; 93 94 ERR_set_mark(); 95 ok = (asn1_d2i_read_bio(in, &mem) >= 0); 96 ERR_pop_to_mark(); 97 if (!ok && mem != NULL) { 98 BUF_MEM_free(mem); 99 mem = NULL; 100 } 101 BIO_free(in); 102 103 /* any2obj_decode_final() frees |mem| for us */ 104 return any2obj_decode_final(provctx, OSSL_OBJECT_UNKNOWN, mem, 105 data_cb, data_cbarg); 106 } 107 108 static OSSL_FUNC_decoder_decode_fn msblob2obj_decode; 109 static int msblob2obj_decode(void *provctx, OSSL_CORE_BIO *cin, int selection, 110 OSSL_CALLBACK *data_cb, void *data_cbarg, 111 OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) 112 { 113 BIO *in = ossl_bio_new_from_core_bio(provctx, cin); 114 BUF_MEM *mem = NULL; 115 size_t mem_len = 0, mem_want; 116 const unsigned char *p; 117 unsigned int bitlen, magic; 118 int isdss = -1; 119 int ispub = -1; 120 int ok = 0; 121 122 if (in == NULL) 123 goto err; 124 125 mem_want = 16; /* The size of the MSBLOB header */ 126 if ((mem = BUF_MEM_new()) == NULL 127 || !BUF_MEM_grow(mem, mem_want)) { 128 ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE); 129 goto err; 130 } 131 132 ERR_set_mark(); 133 ok = BIO_read(in, &mem->data[0], mem_want) == (int)mem_want; 134 mem_len += mem_want; 135 ERR_pop_to_mark(); 136 if (!ok) 137 goto next; 138 139 140 ERR_set_mark(); 141 p = (unsigned char *)&mem->data[0]; 142 ok = ossl_do_blob_header(&p, 16, &magic, &bitlen, &isdss, &ispub) > 0; 143 ERR_pop_to_mark(); 144 if (!ok) 145 goto next; 146 147 ok = 0; 148 mem_want = ossl_blob_length(bitlen, isdss, ispub); 149 if (!BUF_MEM_grow(mem, mem_len + mem_want)) { 150 ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE); 151 goto err; 152 } 153 154 ERR_set_mark(); 155 ok = BIO_read(in, &mem->data[mem_len], mem_want) == (int)mem_want; 156 mem_len += mem_want; 157 ERR_pop_to_mark(); 158 159 next: 160 /* Free resources we no longer need. */ 161 BIO_free(in); 162 if (!ok && mem != NULL) { 163 BUF_MEM_free(mem); 164 mem = NULL; 165 } 166 167 /* any2obj_decode_final() frees |mem| for us */ 168 return any2obj_decode_final(provctx, OSSL_OBJECT_PKEY, mem, 169 data_cb, data_cbarg); 170 171 err: 172 BIO_free(in); 173 BUF_MEM_free(mem); 174 return 0; 175 } 176 177 static OSSL_FUNC_decoder_decode_fn pvk2obj_decode; 178 static int pvk2obj_decode(void *provctx, OSSL_CORE_BIO *cin, int selection, 179 OSSL_CALLBACK *data_cb, void *data_cbarg, 180 OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) 181 { 182 BIO *in = ossl_bio_new_from_core_bio(provctx, cin); 183 BUF_MEM *mem = NULL; 184 size_t mem_len = 0, mem_want; 185 const unsigned char *p; 186 unsigned int saltlen, keylen; 187 int ok = 0; 188 189 if (in == NULL) 190 goto err; 191 192 mem_want = 24; /* The size of the PVK header */ 193 if ((mem = BUF_MEM_new()) == NULL 194 || !BUF_MEM_grow(mem, mem_want)) { 195 ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE); 196 goto err; 197 } 198 199 ERR_set_mark(); 200 ok = BIO_read(in, &mem->data[0], mem_want) == (int)mem_want; 201 mem_len += mem_want; 202 ERR_pop_to_mark(); 203 if (!ok) 204 goto next; 205 206 207 ERR_set_mark(); 208 p = (unsigned char *)&mem->data[0]; 209 ok = ossl_do_PVK_header(&p, 24, 0, &saltlen, &keylen) > 0; 210 ERR_pop_to_mark(); 211 if (!ok) 212 goto next; 213 214 ok = 0; 215 mem_want = saltlen + keylen; 216 if (!BUF_MEM_grow(mem, mem_len + mem_want)) { 217 ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE); 218 goto err; 219 } 220 221 ERR_set_mark(); 222 ok = BIO_read(in, &mem->data[mem_len], mem_want) == (int)mem_want; 223 mem_len += mem_want; 224 ERR_pop_to_mark(); 225 226 next: 227 /* Free resources we no longer need. */ 228 BIO_free(in); 229 if (!ok && mem != NULL) { 230 BUF_MEM_free(mem); 231 mem = NULL; 232 } 233 234 /* any2obj_decode_final() frees |mem| for us */ 235 return any2obj_decode_final(provctx, OSSL_OBJECT_PKEY, mem, 236 data_cb, data_cbarg); 237 238 err: 239 BIO_free(in); 240 BUF_MEM_free(mem); 241 return 0; 242 } 243 244 #define MAKE_DECODER(fromtype, objtype) \ 245 static const OSSL_DISPATCH fromtype##_to_obj_decoder_functions[] = { \ 246 { OSSL_FUNC_DECODER_NEWCTX, (void (*)(void))any2obj_newctx }, \ 247 { OSSL_FUNC_DECODER_FREECTX, (void (*)(void))any2obj_freectx }, \ 248 { OSSL_FUNC_DECODER_DECODE, (void (*)(void))fromtype##2obj_decode }, \ 249 { 0, NULL } \ 250 } 251 252 MAKE_DECODER(der, OSSL_OBJECT_UNKNOWN); 253 MAKE_DECODER(msblob, OSSL_OBJECT_PKEY); 254 MAKE_DECODER(pvk, OSSL_OBJECT_PKEY); 255 256 const OSSL_ALGORITHM ossl_any_to_obj_algorithm[] = { 257 { "obj", "input=DER", der_to_obj_decoder_functions }, 258 { "obj", "input=MSBLOB", msblob_to_obj_decoder_functions }, 259 { "obj", "input=PVK", pvk_to_obj_decoder_functions }, 260 { NULL, } 261 }; 262