1 1.1 christos /* 2 1.1 christos * Copyright 2016-2025 The OpenSSL Project Authors. All Rights Reserved. 3 1.1 christos * 4 1.1 christos * Licensed under the Apache License 2.0 (the "License"). You may not use 5 1.1 christos * this file except in compliance with the License. You can obtain a copy 6 1.1 christos * in the file LICENSE in the source distribution or at 7 1.1 christos * https://www.openssl.org/source/license.html 8 1.1 christos */ 9 1.1 christos 10 1.1 christos /* THIS ENGINE IS FOR TESTING PURPOSES ONLY. */ 11 1.1 christos 12 1.1 christos /* This file has quite some overlap with providers/implementations/storemgmt/file_store.c */ 13 1.1 christos 14 1.1 christos /* We need to use some engine deprecated APIs */ 15 1.1 christos #define OPENSSL_SUPPRESS_DEPRECATED 16 1.1 christos 17 1.1 christos #include "internal/e_os.h" /* for stat */ 18 1.1 christos #include <string.h> 19 1.1 christos #include <sys/stat.h> 20 1.1 christos #include <ctype.h> 21 1.1 christos #include <assert.h> 22 1.1 christos 23 1.1 christos #include <openssl/bio.h> 24 1.1.1.2 christos #include <openssl/dsa.h> /* For d2i_DSAPrivateKey */ 25 1.1 christos #include <openssl/err.h> 26 1.1 christos #include <openssl/evp.h> 27 1.1 christos #include <openssl/pem.h> 28 1.1.1.2 christos #include <openssl/pkcs12.h> /* For the PKCS8 stuff o.O */ 29 1.1.1.2 christos #include <openssl/rsa.h> /* For d2i_RSAPrivateKey */ 30 1.1 christos #include <openssl/safestack.h> 31 1.1 christos #include <openssl/store.h> 32 1.1 christos #include <openssl/ui.h> 33 1.1 christos #include <openssl/engine.h> 34 1.1.1.2 christos #include <openssl/x509.h> /* For the PKCS8 stuff o.O */ 35 1.1.1.2 christos #include "internal/asn1.h" /* For asn1_d2i_read_bio */ 36 1.1 christos #include "internal/o_dir.h" 37 1.1 christos #include "internal/cryptlib.h" 38 1.1.1.2 christos #include "crypto/ctype.h" /* For ossl_isdigit */ 39 1.1.1.2 christos #include "crypto/pem.h" /* For PVK and "blob" PEM headers */ 40 1.1 christos 41 1.1.1.2 christos /* clang-format off */ 42 1.1 christos #include "e_loader_attic_err.c" 43 1.1.1.2 christos /* clang-format on */ 44 1.1 christos 45 1.1 christos DEFINE_STACK_OF(OSSL_STORE_INFO) 46 1.1 christos 47 1.1 christos #ifndef S_ISDIR 48 1.1.1.2 christos #define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR) 49 1.1 christos #endif 50 1.1 christos 51 1.1 christos /*- 52 1.1 christos * Password prompting 53 1.1 christos * ------------------ 54 1.1 christos */ 55 1.1 christos 56 1.1 christos static char *file_get_pass(const UI_METHOD *ui_method, char *pass, 57 1.1.1.2 christos size_t maxsize, const char *desc, const char *info, 58 1.1.1.2 christos void *data) 59 1.1 christos { 60 1.1 christos UI *ui = UI_new(); 61 1.1 christos char *prompt = NULL; 62 1.1 christos 63 1.1 christos if (ui == NULL) { 64 1.1 christos ATTICerr(0, ERR_R_UI_LIB); 65 1.1 christos return NULL; 66 1.1 christos } 67 1.1 christos 68 1.1 christos if (ui_method != NULL) 69 1.1 christos UI_set_method(ui, ui_method); 70 1.1 christos UI_add_user_data(ui, data); 71 1.1 christos 72 1.1 christos if ((prompt = UI_construct_prompt(ui, desc, info)) == NULL) { 73 1.1 christos ATTICerr(0, ERR_R_UI_LIB); 74 1.1 christos pass = NULL; 75 1.1 christos } else if (UI_add_input_string(ui, prompt, UI_INPUT_FLAG_DEFAULT_PWD, 76 1.1.1.2 christos pass, 0, maxsize - 1) 77 1.1.1.2 christos <= 0) { 78 1.1 christos ATTICerr(0, ERR_R_UI_LIB); 79 1.1 christos pass = NULL; 80 1.1 christos } else { 81 1.1 christos switch (UI_process(ui)) { 82 1.1 christos case -2: 83 1.1 christos ATTICerr(0, ATTIC_R_UI_PROCESS_INTERRUPTED_OR_CANCELLED); 84 1.1 christos pass = NULL; 85 1.1 christos break; 86 1.1 christos case -1: 87 1.1 christos ATTICerr(0, ERR_R_UI_LIB); 88 1.1 christos pass = NULL; 89 1.1 christos break; 90 1.1 christos default: 91 1.1 christos break; 92 1.1 christos } 93 1.1 christos } 94 1.1 christos 95 1.1 christos OPENSSL_free(prompt); 96 1.1 christos UI_free(ui); 97 1.1 christos return pass; 98 1.1 christos } 99 1.1 christos 100 1.1 christos struct pem_pass_data { 101 1.1 christos const UI_METHOD *ui_method; 102 1.1 christos void *data; 103 1.1 christos const char *prompt_desc; 104 1.1 christos const char *prompt_info; 105 1.1 christos }; 106 1.1 christos 107 1.1 christos static int file_fill_pem_pass_data(struct pem_pass_data *pass_data, 108 1.1.1.2 christos const char *desc, const char *info, 109 1.1.1.2 christos const UI_METHOD *ui_method, void *ui_data) 110 1.1 christos { 111 1.1 christos if (pass_data == NULL) 112 1.1 christos return 0; 113 1.1 christos pass_data->ui_method = ui_method; 114 1.1 christos pass_data->data = ui_data; 115 1.1 christos pass_data->prompt_desc = desc; 116 1.1 christos pass_data->prompt_info = info; 117 1.1 christos return 1; 118 1.1 christos } 119 1.1 christos 120 1.1 christos /* This is used anywhere a pem_password_cb is needed */ 121 1.1 christos static int file_get_pem_pass(char *buf, int num, int w, void *data) 122 1.1 christos { 123 1.1 christos struct pem_pass_data *pass_data = data; 124 1.1 christos char *pass = file_get_pass(pass_data->ui_method, buf, num, 125 1.1.1.2 christos pass_data->prompt_desc, pass_data->prompt_info, 126 1.1.1.2 christos pass_data->data); 127 1.1 christos 128 1.1 christos return pass == NULL ? 0 : strlen(pass); 129 1.1 christos } 130 1.1 christos 131 1.1 christos /* 132 1.1 christos * Check if |str| ends with |suffix| preceded by a space, and if it does, 133 1.1 christos * return the index of that space. If there is no such suffix in |str|, 134 1.1 christos * return -1. 135 1.1 christos * For |str| == "FOO BAR" and |suffix| == "BAR", the returned value is 3. 136 1.1 christos */ 137 1.1 christos static int check_suffix(const char *str, const char *suffix) 138 1.1 christos { 139 1.1 christos int str_len = strlen(str); 140 1.1 christos int suffix_len = strlen(suffix) + 1; 141 1.1 christos const char *p = NULL; 142 1.1 christos 143 1.1 christos if (suffix_len >= str_len) 144 1.1 christos return -1; 145 1.1 christos p = str + str_len - suffix_len; 146 1.1 christos if (*p != ' ' 147 1.1 christos || strcmp(p + 1, suffix) != 0) 148 1.1 christos return -1; 149 1.1 christos return p - str; 150 1.1 christos } 151 1.1 christos 152 1.1 christos /* 153 1.1 christos * EMBEDDED is a special type of OSSL_STORE_INFO, specially for the file 154 1.1 christos * handlers, so we define it internally. This uses the possibility to 155 1.1 christos * create an OSSL_STORE_INFO with a generic data pointer and arbitrary 156 1.1 christos * type number. 157 1.1 christos * 158 1.1 christos * This is used by a FILE_HANDLER's try_decode function to signal that it 159 1.1 christos * has decoded the incoming blob into a new blob, and that the attempted 160 1.1 christos * decoding should be immediately restarted with the new blob, using the 161 1.1 christos * new PEM name. 162 1.1 christos */ 163 1.1 christos /* Negative numbers are never used for public OSSL_STORE_INFO types */ 164 1.1.1.2 christos #define STORE_INFO_EMBEDDED -1 165 1.1 christos 166 1.1 christos /* This is the embedded data */ 167 1.1 christos struct embedded_st { 168 1.1 christos BUF_MEM *blob; 169 1.1 christos char *pem_name; 170 1.1 christos }; 171 1.1 christos 172 1.1 christos /* Helper functions */ 173 1.1 christos static struct embedded_st *get0_EMBEDDED(OSSL_STORE_INFO *info) 174 1.1 christos { 175 1.1 christos return OSSL_STORE_INFO_get0_data(STORE_INFO_EMBEDDED, info); 176 1.1 christos } 177 1.1 christos 178 1.1 christos static void store_info_free(OSSL_STORE_INFO *info) 179 1.1 christos { 180 1.1 christos struct embedded_st *data; 181 1.1 christos 182 1.1 christos if (info != NULL && (data = get0_EMBEDDED(info)) != NULL) { 183 1.1 christos BUF_MEM_free(data->blob); 184 1.1 christos OPENSSL_free(data->pem_name); 185 1.1 christos OPENSSL_free(data); 186 1.1 christos } 187 1.1 christos OSSL_STORE_INFO_free(info); 188 1.1 christos } 189 1.1 christos 190 1.1 christos static OSSL_STORE_INFO *new_EMBEDDED(const char *new_pem_name, 191 1.1.1.2 christos BUF_MEM *embedded) 192 1.1 christos { 193 1.1 christos OSSL_STORE_INFO *info = NULL; 194 1.1 christos struct embedded_st *data = NULL; 195 1.1 christos 196 1.1 christos if ((data = OPENSSL_zalloc(sizeof(*data))) == NULL) 197 1.1 christos return NULL; 198 1.1 christos if ((info = OSSL_STORE_INFO_new(STORE_INFO_EMBEDDED, data)) == NULL) { 199 1.1 christos ATTICerr(0, ERR_R_OSSL_STORE_LIB); 200 1.1 christos OPENSSL_free(data); 201 1.1 christos return NULL; 202 1.1 christos } 203 1.1 christos 204 1.1 christos data->blob = embedded; 205 1.1.1.2 christos data->pem_name = new_pem_name == NULL ? NULL : OPENSSL_strdup(new_pem_name); 206 1.1 christos 207 1.1 christos if (new_pem_name != NULL && data->pem_name == NULL) { 208 1.1 christos store_info_free(info); 209 1.1 christos info = NULL; 210 1.1 christos } 211 1.1 christos 212 1.1 christos return info; 213 1.1 christos } 214 1.1 christos 215 1.1 christos /*- 216 1.1 christos * The file scheme decoders 217 1.1 christos * ------------------------ 218 1.1 christos * 219 1.1 christos * Each possible data type has its own decoder, which either operates 220 1.1 christos * through a given PEM name, or attempts to decode to see if the blob 221 1.1 christos * it's given is decodable for its data type. The assumption is that 222 1.1 christos * only the correct data type will match the content. 223 1.1 christos */ 224 1.1 christos 225 1.1 christos /*- 226 1.1 christos * The try_decode function is called to check if the blob of data can 227 1.1 christos * be used by this handler, and if it can, decodes it into a supported 228 1.1 christos * OpenSSL type and returns an OSSL_STORE_INFO with the decoded data. 229 1.1 christos * Input: 230 1.1 christos * pem_name: If this blob comes from a PEM file, this holds 231 1.1 christos * the PEM name. If it comes from another type of 232 1.1 christos * file, this is NULL. 233 1.1 christos * pem_header: If this blob comes from a PEM file, this holds 234 1.1 christos * the PEM headers. If it comes from another type of 235 1.1 christos * file, this is NULL. 236 1.1 christos * blob: The blob of data to match with what this handler 237 1.1 christos * can use. 238 1.1 christos * len: The length of the blob. 239 1.1 christos * handler_ctx: For a handler marked repeatable, this pointer can 240 1.1 christos * be used to create a context for the handler. IT IS 241 1.1 christos * THE HANDLER'S RESPONSIBILITY TO CREATE AND DESTROY 242 1.1 christos * THIS CONTEXT APPROPRIATELY, i.e. create on first call 243 1.1 christos * and destroy when about to return NULL. 244 1.1 christos * matchcount: A pointer to an int to count matches for this data. 245 1.1 christos * Usually becomes 0 (no match) or 1 (match!), but may 246 1.1 christos * be higher in the (unlikely) event that the data matches 247 1.1 christos * more than one possibility. The int will always be 248 1.1 christos * zero when the function is called. 249 1.1 christos * ui_method: Application UI method for getting a password, pin 250 1.1 christos * or any other interactive data. 251 1.1 christos * ui_data: Application data to be passed to ui_method when 252 1.1 christos * it's called. 253 1.1 christos * libctx: The library context to be used if applicable 254 1.1 christos * propq: The property query string for any algorithm fetches 255 1.1 christos * Output: 256 1.1 christos * an OSSL_STORE_INFO 257 1.1 christos */ 258 1.1 christos typedef OSSL_STORE_INFO *(*file_try_decode_fn)(const char *pem_name, 259 1.1.1.2 christos const char *pem_header, 260 1.1.1.2 christos const unsigned char *blob, 261 1.1.1.2 christos size_t len, void **handler_ctx, 262 1.1.1.2 christos int *matchcount, 263 1.1.1.2 christos const UI_METHOD *ui_method, 264 1.1.1.2 christos void *ui_data, const char *uri, 265 1.1.1.2 christos OSSL_LIB_CTX *libctx, 266 1.1.1.2 christos const char *propq); 267 1.1 christos /* 268 1.1 christos * The eof function should return 1 if there's no more data to be found 269 1.1 christos * with the handler_ctx, otherwise 0. This is only used when the handler is 270 1.1 christos * marked repeatable. 271 1.1 christos */ 272 1.1 christos typedef int (*file_eof_fn)(void *handler_ctx); 273 1.1 christos /* 274 1.1 christos * The destroy_ctx function is used to destroy the handler_ctx that was 275 1.1 christos * initiated by a repeatable try_decode function. This is only used when 276 1.1 christos * the handler is marked repeatable. 277 1.1 christos */ 278 1.1 christos typedef void (*file_destroy_ctx_fn)(void **handler_ctx); 279 1.1 christos 280 1.1 christos typedef struct file_handler_st { 281 1.1 christos const char *name; 282 1.1 christos file_try_decode_fn try_decode; 283 1.1 christos file_eof_fn eof; 284 1.1 christos file_destroy_ctx_fn destroy_ctx; 285 1.1 christos 286 1.1 christos /* flags */ 287 1.1 christos int repeatable; 288 1.1 christos } FILE_HANDLER; 289 1.1 christos 290 1.1 christos /* 291 1.1 christos * PKCS#12 decoder. It operates by decoding all of the blob content, 292 1.1 christos * extracting all the interesting data from it and storing them internally, 293 1.1 christos * then serving them one piece at a time. 294 1.1 christos */ 295 1.1 christos static OSSL_STORE_INFO *try_decode_PKCS12(const char *pem_name, 296 1.1.1.2 christos const char *pem_header, 297 1.1.1.2 christos const unsigned char *blob, 298 1.1.1.2 christos size_t len, void **pctx, 299 1.1.1.2 christos int *matchcount, 300 1.1.1.2 christos const UI_METHOD *ui_method, 301 1.1.1.2 christos void *ui_data, const char *uri, 302 1.1.1.2 christos OSSL_LIB_CTX *libctx, 303 1.1.1.2 christos const char *propq) 304 1.1 christos { 305 1.1 christos OSSL_STORE_INFO *store_info = NULL; 306 1.1 christos STACK_OF(OSSL_STORE_INFO) *ctx = *pctx; 307 1.1 christos 308 1.1 christos if (ctx == NULL) { 309 1.1 christos /* Initial parsing */ 310 1.1 christos PKCS12 *p12; 311 1.1 christos 312 1.1 christos if (pem_name != NULL) 313 1.1 christos /* No match, there is no PEM PKCS12 tag */ 314 1.1 christos return NULL; 315 1.1 christos 316 1.1 christos if ((p12 = d2i_PKCS12(NULL, &blob, len)) != NULL) { 317 1.1 christos char *pass = NULL; 318 1.1 christos char tpass[PEM_BUFSIZE]; 319 1.1 christos EVP_PKEY *pkey = NULL; 320 1.1 christos X509 *cert = NULL; 321 1.1 christos STACK_OF(X509) *chain = NULL; 322 1.1 christos 323 1.1 christos *matchcount = 1; 324 1.1 christos 325 1.1 christos if (!PKCS12_mac_present(p12) 326 1.1 christos || PKCS12_verify_mac(p12, "", 0) 327 1.1 christos || PKCS12_verify_mac(p12, NULL, 0)) { 328 1.1 christos pass = ""; 329 1.1 christos } else { 330 1.1 christos if ((pass = file_get_pass(ui_method, tpass, PEM_BUFSIZE, 331 1.1.1.2 christos "PKCS12 import", uri, 332 1.1.1.2 christos ui_data)) 333 1.1.1.2 christos == NULL) { 334 1.1 christos ATTICerr(0, ATTIC_R_PASSPHRASE_CALLBACK_ERROR); 335 1.1 christos goto p12_end; 336 1.1 christos } 337 1.1 christos if (!PKCS12_verify_mac(p12, pass, strlen(pass))) { 338 1.1 christos ATTICerr(0, ATTIC_R_ERROR_VERIFYING_PKCS12_MAC); 339 1.1 christos goto p12_end; 340 1.1 christos } 341 1.1 christos } 342 1.1 christos 343 1.1 christos if (PKCS12_parse(p12, pass, &pkey, &cert, &chain)) { 344 1.1 christos OSSL_STORE_INFO *osi_pkey = NULL; 345 1.1 christos OSSL_STORE_INFO *osi_cert = NULL; 346 1.1 christos OSSL_STORE_INFO *osi_ca = NULL; 347 1.1 christos int ok = 1; 348 1.1 christos 349 1.1 christos if ((ctx = sk_OSSL_STORE_INFO_new_null()) != NULL) { 350 1.1 christos if (pkey != NULL) { 351 1.1 christos if ((osi_pkey = OSSL_STORE_INFO_new_PKEY(pkey)) != NULL 352 1.1 christos /* clearing pkey here avoids case distinctions */ 353 1.1 christos && (pkey = NULL) == NULL 354 1.1 christos && sk_OSSL_STORE_INFO_push(ctx, osi_pkey) != 0) 355 1.1 christos osi_pkey = NULL; 356 1.1 christos else 357 1.1 christos ok = 0; 358 1.1 christos } 359 1.1 christos if (ok && cert != NULL) { 360 1.1 christos if ((osi_cert = OSSL_STORE_INFO_new_CERT(cert)) != NULL 361 1.1 christos /* clearing cert here avoids case distinctions */ 362 1.1 christos && (cert = NULL) == NULL 363 1.1 christos && sk_OSSL_STORE_INFO_push(ctx, osi_cert) != 0) 364 1.1 christos osi_cert = NULL; 365 1.1 christos else 366 1.1 christos ok = 0; 367 1.1 christos } 368 1.1 christos while (ok && sk_X509_num(chain) > 0) { 369 1.1 christos X509 *ca = sk_X509_value(chain, 0); 370 1.1 christos 371 1.1 christos if ((osi_ca = OSSL_STORE_INFO_new_CERT(ca)) != NULL 372 1.1 christos && sk_X509_shift(chain) != NULL 373 1.1 christos && sk_OSSL_STORE_INFO_push(ctx, osi_ca) != 0) 374 1.1 christos osi_ca = NULL; 375 1.1 christos else 376 1.1 christos ok = 0; 377 1.1 christos } 378 1.1 christos } 379 1.1 christos EVP_PKEY_free(pkey); 380 1.1 christos X509_free(cert); 381 1.1 christos OSSL_STACK_OF_X509_free(chain); 382 1.1 christos store_info_free(osi_pkey); 383 1.1 christos store_info_free(osi_cert); 384 1.1 christos store_info_free(osi_ca); 385 1.1 christos if (!ok) { 386 1.1 christos sk_OSSL_STORE_INFO_pop_free(ctx, store_info_free); 387 1.1 christos ctx = NULL; 388 1.1 christos } 389 1.1 christos *pctx = ctx; 390 1.1 christos } 391 1.1 christos } 392 1.1.1.2 christos p12_end: 393 1.1 christos PKCS12_free(p12); 394 1.1 christos if (ctx == NULL) 395 1.1 christos return NULL; 396 1.1 christos } 397 1.1 christos 398 1.1 christos *matchcount = 1; 399 1.1 christos store_info = sk_OSSL_STORE_INFO_shift(ctx); 400 1.1 christos return store_info; 401 1.1 christos } 402 1.1 christos 403 1.1 christos static int eof_PKCS12(void *ctx_) 404 1.1 christos { 405 1.1 christos STACK_OF(OSSL_STORE_INFO) *ctx = ctx_; 406 1.1 christos 407 1.1 christos return ctx == NULL || sk_OSSL_STORE_INFO_num(ctx) == 0; 408 1.1 christos } 409 1.1 christos 410 1.1 christos static void destroy_ctx_PKCS12(void **pctx) 411 1.1 christos { 412 1.1 christos STACK_OF(OSSL_STORE_INFO) *ctx = *pctx; 413 1.1 christos 414 1.1 christos sk_OSSL_STORE_INFO_pop_free(ctx, store_info_free); 415 1.1 christos *pctx = NULL; 416 1.1 christos } 417 1.1 christos 418 1.1 christos static FILE_HANDLER PKCS12_handler = { 419 1.1 christos "PKCS12", 420 1.1 christos try_decode_PKCS12, 421 1.1 christos eof_PKCS12, 422 1.1 christos destroy_ctx_PKCS12, 423 1.1 christos 1 /* repeatable */ 424 1.1 christos }; 425 1.1 christos 426 1.1 christos /* 427 1.1 christos * Encrypted PKCS#8 decoder. It operates by just decrypting the given blob 428 1.1 christos * into a new blob, which is returned as an EMBEDDED STORE_INFO. The whole 429 1.1 christos * decoding process will then start over with the new blob. 430 1.1 christos */ 431 1.1 christos static OSSL_STORE_INFO *try_decode_PKCS8Encrypted(const char *pem_name, 432 1.1.1.2 christos const char *pem_header, 433 1.1.1.2 christos const unsigned char *blob, 434 1.1.1.2 christos size_t len, void **pctx, 435 1.1.1.2 christos int *matchcount, 436 1.1.1.2 christos const UI_METHOD *ui_method, 437 1.1.1.2 christos void *ui_data, 438 1.1.1.2 christos const char *uri, 439 1.1.1.2 christos OSSL_LIB_CTX *libctx, 440 1.1.1.2 christos const char *propq) 441 1.1 christos { 442 1.1 christos X509_SIG *p8 = NULL; 443 1.1 christos char kbuf[PEM_BUFSIZE]; 444 1.1 christos char *pass = NULL; 445 1.1 christos const X509_ALGOR *dalg = NULL; 446 1.1 christos const ASN1_OCTET_STRING *doct = NULL; 447 1.1 christos OSSL_STORE_INFO *store_info = NULL; 448 1.1 christos BUF_MEM *mem = NULL; 449 1.1 christos unsigned char *new_data = NULL; 450 1.1 christos int new_data_len; 451 1.1 christos 452 1.1 christos if (pem_name != NULL) { 453 1.1 christos if (strcmp(pem_name, PEM_STRING_PKCS8) != 0) 454 1.1 christos return NULL; 455 1.1 christos *matchcount = 1; 456 1.1 christos } 457 1.1 christos 458 1.1 christos if ((p8 = d2i_X509_SIG(NULL, &blob, len)) == NULL) 459 1.1 christos return NULL; 460 1.1 christos 461 1.1 christos *matchcount = 1; 462 1.1 christos 463 1.1 christos if ((mem = BUF_MEM_new()) == NULL) { 464 1.1 christos ATTICerr(0, ERR_R_BUF_LIB); 465 1.1 christos goto nop8; 466 1.1 christos } 467 1.1 christos 468 1.1 christos if ((pass = file_get_pass(ui_method, kbuf, PEM_BUFSIZE, 469 1.1.1.2 christos "PKCS8 decrypt pass phrase", uri, 470 1.1.1.2 christos ui_data)) 471 1.1.1.2 christos == NULL) { 472 1.1 christos ATTICerr(0, ATTIC_R_BAD_PASSWORD_READ); 473 1.1 christos goto nop8; 474 1.1 christos } 475 1.1 christos 476 1.1 christos X509_SIG_get0(p8, &dalg, &doct); 477 1.1 christos if (!PKCS12_pbe_crypt(dalg, pass, strlen(pass), doct->data, doct->length, 478 1.1.1.2 christos &new_data, &new_data_len, 0)) 479 1.1 christos goto nop8; 480 1.1 christos 481 1.1 christos mem->data = (char *)new_data; 482 1.1 christos mem->max = mem->length = (size_t)new_data_len; 483 1.1 christos X509_SIG_free(p8); 484 1.1 christos p8 = NULL; 485 1.1 christos 486 1.1 christos store_info = new_EMBEDDED(PEM_STRING_PKCS8INF, mem); 487 1.1 christos if (store_info == NULL) { 488 1.1 christos ATTICerr(0, ERR_R_OSSL_STORE_LIB); 489 1.1 christos goto nop8; 490 1.1 christos } 491 1.1 christos 492 1.1 christos return store_info; 493 1.1.1.2 christos nop8: 494 1.1 christos X509_SIG_free(p8); 495 1.1 christos BUF_MEM_free(mem); 496 1.1 christos return NULL; 497 1.1 christos } 498 1.1 christos 499 1.1 christos static FILE_HANDLER PKCS8Encrypted_handler = { 500 1.1 christos "PKCS8Encrypted", 501 1.1 christos try_decode_PKCS8Encrypted 502 1.1 christos }; 503 1.1 christos 504 1.1 christos /* 505 1.1 christos * Private key decoder. Decodes all sorts of private keys, both PKCS#8 506 1.1 christos * encoded ones and old style PEM ones (with the key type is encoded into 507 1.1 christos * the PEM name). 508 1.1 christos */ 509 1.1 christos static OSSL_STORE_INFO *try_decode_PrivateKey(const char *pem_name, 510 1.1.1.2 christos const char *pem_header, 511 1.1.1.2 christos const unsigned char *blob, 512 1.1.1.2 christos size_t len, void **pctx, 513 1.1.1.2 christos int *matchcount, 514 1.1.1.2 christos const UI_METHOD *ui_method, 515 1.1.1.2 christos void *ui_data, const char *uri, 516 1.1.1.2 christos OSSL_LIB_CTX *libctx, 517 1.1.1.2 christos const char *propq) 518 1.1 christos { 519 1.1 christos OSSL_STORE_INFO *store_info = NULL; 520 1.1 christos EVP_PKEY *pkey = NULL; 521 1.1 christos const EVP_PKEY_ASN1_METHOD *ameth = NULL; 522 1.1 christos 523 1.1 christos if (pem_name != NULL) { 524 1.1 christos if (strcmp(pem_name, PEM_STRING_PKCS8INF) == 0) { 525 1.1.1.2 christos PKCS8_PRIV_KEY_INFO *p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &blob, len); 526 1.1 christos 527 1.1 christos *matchcount = 1; 528 1.1 christos if (p8inf != NULL) 529 1.1 christos pkey = EVP_PKCS82PKEY_ex(p8inf, libctx, propq); 530 1.1 christos PKCS8_PRIV_KEY_INFO_free(p8inf); 531 1.1 christos } else { 532 1.1 christos int slen; 533 1.1 christos int pkey_id; 534 1.1 christos 535 1.1 christos if ((slen = check_suffix(pem_name, "PRIVATE KEY")) > 0 536 1.1 christos && (ameth = EVP_PKEY_asn1_find_str(NULL, pem_name, 537 1.1.1.2 christos slen)) 538 1.1.1.2 christos != NULL 539 1.1 christos && EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, 540 1.1.1.2 christos ameth)) { 541 1.1 christos *matchcount = 1; 542 1.1 christos pkey = d2i_PrivateKey_ex(pkey_id, NULL, &blob, len, 543 1.1.1.2 christos libctx, propq); 544 1.1 christos } 545 1.1 christos } 546 1.1 christos } else { 547 1.1 christos int i; 548 1.1 christos #ifndef OPENSSL_NO_ENGINE 549 1.1 christos ENGINE *curengine = ENGINE_get_first(); 550 1.1 christos 551 1.1 christos while (curengine != NULL) { 552 1.1.1.2 christos ENGINE_PKEY_ASN1_METHS_PTR asn1meths = ENGINE_get_pkey_asn1_meths(curengine); 553 1.1 christos 554 1.1 christos if (asn1meths != NULL) { 555 1.1 christos const int *nids = NULL; 556 1.1 christos int nids_n = asn1meths(curengine, NULL, &nids, 0); 557 1.1 christos 558 1.1 christos for (i = 0; i < nids_n; i++) { 559 1.1 christos EVP_PKEY_ASN1_METHOD *ameth2 = NULL; 560 1.1 christos EVP_PKEY *tmp_pkey = NULL; 561 1.1 christos const unsigned char *tmp_blob = blob; 562 1.1 christos int pkey_id, pkey_flags; 563 1.1 christos 564 1.1 christos if (!asn1meths(curengine, &ameth2, NULL, nids[i]) 565 1.1 christos || !EVP_PKEY_asn1_get0_info(&pkey_id, NULL, 566 1.1.1.2 christos &pkey_flags, NULL, NULL, 567 1.1.1.2 christos ameth2) 568 1.1 christos || (pkey_flags & ASN1_PKEY_ALIAS) != 0) 569 1.1 christos continue; 570 1.1 christos 571 1.1 christos ERR_set_mark(); /* prevent flooding error queue */ 572 1.1 christos tmp_pkey = d2i_PrivateKey_ex(pkey_id, NULL, 573 1.1.1.2 christos &tmp_blob, len, 574 1.1.1.2 christos libctx, propq); 575 1.1 christos if (tmp_pkey != NULL) { 576 1.1 christos if (pkey != NULL) 577 1.1 christos EVP_PKEY_free(tmp_pkey); 578 1.1 christos else 579 1.1 christos pkey = tmp_pkey; 580 1.1 christos (*matchcount)++; 581 1.1 christos } 582 1.1 christos ERR_pop_to_mark(); 583 1.1 christos } 584 1.1 christos } 585 1.1 christos curengine = ENGINE_get_next(curengine); 586 1.1 christos } 587 1.1 christos #endif 588 1.1 christos 589 1.1 christos for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) { 590 1.1 christos EVP_PKEY *tmp_pkey = NULL; 591 1.1 christos const unsigned char *tmp_blob = blob; 592 1.1 christos int pkey_id, pkey_flags; 593 1.1 christos 594 1.1 christos ameth = EVP_PKEY_asn1_get0(i); 595 1.1 christos if (!EVP_PKEY_asn1_get0_info(&pkey_id, NULL, &pkey_flags, NULL, 596 1.1.1.2 christos NULL, ameth) 597 1.1 christos || (pkey_flags & ASN1_PKEY_ALIAS) != 0) 598 1.1 christos continue; 599 1.1 christos 600 1.1 christos ERR_set_mark(); /* prevent flooding error queue */ 601 1.1 christos tmp_pkey = d2i_PrivateKey_ex(pkey_id, NULL, &tmp_blob, len, 602 1.1.1.2 christos libctx, propq); 603 1.1 christos if (tmp_pkey != NULL) { 604 1.1 christos if (pkey != NULL) 605 1.1 christos EVP_PKEY_free(tmp_pkey); 606 1.1 christos else 607 1.1 christos pkey = tmp_pkey; 608 1.1 christos (*matchcount)++; 609 1.1 christos } 610 1.1 christos ERR_pop_to_mark(); 611 1.1 christos } 612 1.1 christos 613 1.1 christos if (*matchcount > 1) { 614 1.1 christos EVP_PKEY_free(pkey); 615 1.1 christos pkey = NULL; 616 1.1 christos } 617 1.1 christos } 618 1.1 christos if (pkey == NULL) 619 1.1 christos /* No match */ 620 1.1 christos return NULL; 621 1.1 christos 622 1.1 christos store_info = OSSL_STORE_INFO_new_PKEY(pkey); 623 1.1 christos if (store_info == NULL) 624 1.1 christos EVP_PKEY_free(pkey); 625 1.1 christos 626 1.1 christos return store_info; 627 1.1 christos } 628 1.1 christos 629 1.1 christos static FILE_HANDLER PrivateKey_handler = { 630 1.1 christos "PrivateKey", 631 1.1 christos try_decode_PrivateKey 632 1.1 christos }; 633 1.1 christos 634 1.1 christos /* 635 1.1 christos * Public key decoder. Only supports SubjectPublicKeyInfo formatted keys. 636 1.1 christos */ 637 1.1 christos static OSSL_STORE_INFO *try_decode_PUBKEY(const char *pem_name, 638 1.1.1.2 christos const char *pem_header, 639 1.1.1.2 christos const unsigned char *blob, 640 1.1.1.2 christos size_t len, void **pctx, 641 1.1.1.2 christos int *matchcount, 642 1.1.1.2 christos const UI_METHOD *ui_method, 643 1.1.1.2 christos void *ui_data, const char *uri, 644 1.1.1.2 christos OSSL_LIB_CTX *libctx, 645 1.1.1.2 christos const char *propq) 646 1.1 christos { 647 1.1 christos OSSL_STORE_INFO *store_info = NULL; 648 1.1 christos EVP_PKEY *pkey = NULL; 649 1.1 christos 650 1.1 christos if (pem_name != NULL) { 651 1.1 christos if (strcmp(pem_name, PEM_STRING_PUBLIC) != 0) 652 1.1 christos /* No match */ 653 1.1 christos return NULL; 654 1.1 christos *matchcount = 1; 655 1.1 christos } 656 1.1 christos 657 1.1 christos if ((pkey = d2i_PUBKEY(NULL, &blob, len)) != NULL) { 658 1.1 christos *matchcount = 1; 659 1.1 christos store_info = OSSL_STORE_INFO_new_PUBKEY(pkey); 660 1.1 christos } 661 1.1 christos 662 1.1 christos return store_info; 663 1.1 christos } 664 1.1 christos 665 1.1 christos static FILE_HANDLER PUBKEY_handler = { 666 1.1 christos "PUBKEY", 667 1.1 christos try_decode_PUBKEY 668 1.1 christos }; 669 1.1 christos 670 1.1 christos /* 671 1.1 christos * Key parameter decoder. 672 1.1 christos */ 673 1.1 christos static OSSL_STORE_INFO *try_decode_params(const char *pem_name, 674 1.1.1.2 christos const char *pem_header, 675 1.1.1.2 christos const unsigned char *blob, 676 1.1.1.2 christos size_t len, void **pctx, 677 1.1.1.2 christos int *matchcount, 678 1.1.1.2 christos const UI_METHOD *ui_method, 679 1.1.1.2 christos void *ui_data, const char *uri, 680 1.1.1.2 christos OSSL_LIB_CTX *libctx, 681 1.1.1.2 christos const char *propq) 682 1.1 christos { 683 1.1 christos OSSL_STORE_INFO *store_info = NULL; 684 1.1 christos EVP_PKEY *pkey = NULL; 685 1.1 christos const EVP_PKEY_ASN1_METHOD *ameth = NULL; 686 1.1 christos 687 1.1 christos if (pem_name != NULL) { 688 1.1 christos int slen; 689 1.1 christos int pkey_id; 690 1.1 christos 691 1.1 christos if ((slen = check_suffix(pem_name, "PARAMETERS")) > 0 692 1.1 christos && (ameth = EVP_PKEY_asn1_find_str(NULL, pem_name, slen)) != NULL 693 1.1 christos && EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, 694 1.1.1.2 christos ameth)) { 695 1.1 christos *matchcount = 1; 696 1.1 christos pkey = d2i_KeyParams(pkey_id, NULL, &blob, len); 697 1.1 christos } 698 1.1 christos } else { 699 1.1 christos int i; 700 1.1 christos 701 1.1 christos for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) { 702 1.1 christos EVP_PKEY *tmp_pkey = NULL; 703 1.1 christos const unsigned char *tmp_blob = blob; 704 1.1 christos int pkey_id, pkey_flags; 705 1.1 christos 706 1.1 christos ameth = EVP_PKEY_asn1_get0(i); 707 1.1 christos if (!EVP_PKEY_asn1_get0_info(&pkey_id, NULL, &pkey_flags, NULL, 708 1.1.1.2 christos NULL, ameth) 709 1.1 christos || (pkey_flags & ASN1_PKEY_ALIAS) != 0) 710 1.1 christos continue; 711 1.1 christos 712 1.1 christos ERR_set_mark(); /* prevent flooding error queue */ 713 1.1 christos 714 1.1 christos tmp_pkey = d2i_KeyParams(pkey_id, NULL, &tmp_blob, len); 715 1.1 christos 716 1.1 christos if (tmp_pkey != NULL) { 717 1.1 christos if (pkey != NULL) 718 1.1 christos EVP_PKEY_free(tmp_pkey); 719 1.1 christos else 720 1.1 christos pkey = tmp_pkey; 721 1.1 christos (*matchcount)++; 722 1.1 christos } 723 1.1 christos ERR_pop_to_mark(); 724 1.1 christos } 725 1.1 christos 726 1.1 christos if (*matchcount > 1) { 727 1.1 christos EVP_PKEY_free(pkey); 728 1.1 christos pkey = NULL; 729 1.1 christos } 730 1.1 christos } 731 1.1 christos if (pkey == NULL) 732 1.1 christos /* No match */ 733 1.1 christos return NULL; 734 1.1 christos 735 1.1 christos store_info = OSSL_STORE_INFO_new_PARAMS(pkey); 736 1.1 christos if (store_info == NULL) 737 1.1 christos EVP_PKEY_free(pkey); 738 1.1 christos 739 1.1 christos return store_info; 740 1.1 christos } 741 1.1 christos 742 1.1 christos static FILE_HANDLER params_handler = { 743 1.1 christos "params", 744 1.1 christos try_decode_params 745 1.1 christos }; 746 1.1 christos 747 1.1 christos /* 748 1.1 christos * X.509 certificate decoder. 749 1.1 christos */ 750 1.1 christos static OSSL_STORE_INFO *try_decode_X509Certificate(const char *pem_name, 751 1.1.1.2 christos const char *pem_header, 752 1.1.1.2 christos const unsigned char *blob, 753 1.1.1.2 christos size_t len, void **pctx, 754 1.1.1.2 christos int *matchcount, 755 1.1.1.2 christos const UI_METHOD *ui_method, 756 1.1.1.2 christos void *ui_data, 757 1.1.1.2 christos const char *uri, 758 1.1.1.2 christos OSSL_LIB_CTX *libctx, 759 1.1.1.2 christos const char *propq) 760 1.1 christos { 761 1.1 christos OSSL_STORE_INFO *store_info = NULL; 762 1.1 christos X509 *cert = NULL; 763 1.1 christos 764 1.1 christos /* 765 1.1 christos * In most cases, we can try to interpret the serialized data as a trusted 766 1.1 christos * cert (X509 + X509_AUX) and fall back to reading it as a normal cert 767 1.1 christos * (just X509), but if the PEM name specifically declares it as a trusted 768 1.1 christos * cert, then no fallback should be engaged. |ignore_trusted| tells if 769 1.1 christos * the fallback can be used (1) or not (0). 770 1.1 christos */ 771 1.1 christos int ignore_trusted = 1; 772 1.1 christos 773 1.1 christos if (pem_name != NULL) { 774 1.1 christos if (strcmp(pem_name, PEM_STRING_X509_TRUSTED) == 0) 775 1.1 christos ignore_trusted = 0; 776 1.1 christos else if (strcmp(pem_name, PEM_STRING_X509_OLD) != 0 777 1.1.1.2 christos && strcmp(pem_name, PEM_STRING_X509) != 0) 778 1.1 christos /* No match */ 779 1.1 christos return NULL; 780 1.1 christos *matchcount = 1; 781 1.1 christos } 782 1.1 christos 783 1.1 christos cert = X509_new_ex(libctx, propq); 784 1.1 christos if (cert == NULL) 785 1.1 christos return NULL; 786 1.1 christos 787 1.1 christos if ((d2i_X509_AUX(&cert, &blob, len)) != NULL 788 1.1 christos || (ignore_trusted && (d2i_X509(&cert, &blob, len)) != NULL)) { 789 1.1 christos *matchcount = 1; 790 1.1 christos store_info = OSSL_STORE_INFO_new_CERT(cert); 791 1.1 christos } 792 1.1 christos 793 1.1 christos if (store_info == NULL) 794 1.1 christos X509_free(cert); 795 1.1 christos 796 1.1 christos return store_info; 797 1.1 christos } 798 1.1 christos 799 1.1 christos static FILE_HANDLER X509Certificate_handler = { 800 1.1 christos "X509Certificate", 801 1.1 christos try_decode_X509Certificate 802 1.1 christos }; 803 1.1 christos 804 1.1 christos /* 805 1.1 christos * X.509 CRL decoder. 806 1.1 christos */ 807 1.1 christos static OSSL_STORE_INFO *try_decode_X509CRL(const char *pem_name, 808 1.1.1.2 christos const char *pem_header, 809 1.1.1.2 christos const unsigned char *blob, 810 1.1.1.2 christos size_t len, void **pctx, 811 1.1.1.2 christos int *matchcount, 812 1.1.1.2 christos const UI_METHOD *ui_method, 813 1.1.1.2 christos void *ui_data, const char *uri, 814 1.1.1.2 christos OSSL_LIB_CTX *libctx, 815 1.1.1.2 christos const char *propq) 816 1.1 christos { 817 1.1 christos OSSL_STORE_INFO *store_info = NULL; 818 1.1 christos X509_CRL *crl = NULL; 819 1.1 christos 820 1.1 christos if (pem_name != NULL) { 821 1.1 christos if (strcmp(pem_name, PEM_STRING_X509_CRL) != 0) 822 1.1 christos /* No match */ 823 1.1 christos return NULL; 824 1.1 christos *matchcount = 1; 825 1.1 christos } 826 1.1 christos 827 1.1 christos if ((crl = d2i_X509_CRL(NULL, &blob, len)) != NULL) { 828 1.1 christos *matchcount = 1; 829 1.1 christos store_info = OSSL_STORE_INFO_new_CRL(crl); 830 1.1 christos } 831 1.1 christos 832 1.1 christos if (store_info == NULL) 833 1.1 christos X509_CRL_free(crl); 834 1.1 christos 835 1.1 christos return store_info; 836 1.1 christos } 837 1.1 christos 838 1.1 christos static FILE_HANDLER X509CRL_handler = { 839 1.1 christos "X509CRL", 840 1.1 christos try_decode_X509CRL 841 1.1 christos }; 842 1.1 christos 843 1.1 christos /* 844 1.1 christos * To finish it all off, we collect all the handlers. 845 1.1 christos */ 846 1.1 christos static const FILE_HANDLER *file_handlers[] = { 847 1.1 christos &PKCS12_handler, 848 1.1 christos &PKCS8Encrypted_handler, 849 1.1 christos &X509Certificate_handler, 850 1.1 christos &X509CRL_handler, 851 1.1 christos ¶ms_handler, 852 1.1 christos &PUBKEY_handler, 853 1.1 christos &PrivateKey_handler, 854 1.1 christos }; 855 1.1 christos 856 1.1 christos /*- 857 1.1 christos * The loader itself 858 1.1 christos * ----------------- 859 1.1 christos */ 860 1.1 christos 861 1.1 christos struct ossl_store_loader_ctx_st { 862 1.1.1.2 christos char *uri; /* The URI we currently try to load */ 863 1.1 christos enum { 864 1.1 christos is_raw = 0, 865 1.1 christos is_pem, 866 1.1 christos is_dir 867 1.1 christos } type; 868 1.1 christos int errcnt; 869 1.1.1.2 christos #define FILE_FLAG_SECMEM (1 << 0) 870 1.1.1.2 christos #define FILE_FLAG_ATTACHED (1 << 1) 871 1.1 christos unsigned int flags; 872 1.1 christos union { 873 1.1 christos struct { /* Used with is_raw and is_pem */ 874 1.1 christos BIO *file; 875 1.1 christos 876 1.1 christos /* 877 1.1 christos * The following are used when the handler is marked as 878 1.1 christos * repeatable 879 1.1 christos */ 880 1.1 christos const FILE_HANDLER *last_handler; 881 1.1 christos void *last_handler_ctx; 882 1.1 christos } file; 883 1.1 christos struct { /* Used with is_dir */ 884 1.1 christos OPENSSL_DIR_CTX *ctx; 885 1.1 christos int end_reached; 886 1.1 christos 887 1.1 christos /* 888 1.1 christos * When a search expression is given, these are filled in. 889 1.1 christos * |search_name| contains the file basename to look for. 890 1.1 christos * The string is exactly 8 characters long. 891 1.1 christos */ 892 1.1 christos char search_name[9]; 893 1.1 christos 894 1.1 christos /* 895 1.1 christos * The directory reading utility we have combines opening with 896 1.1 christos * reading the first name. To make sure we can detect the end 897 1.1 christos * at the right time, we read early and cache the name. 898 1.1 christos */ 899 1.1 christos const char *last_entry; 900 1.1 christos int last_errno; 901 1.1 christos } dir; 902 1.1 christos } _; 903 1.1 christos 904 1.1 christos /* Expected object type. May be unspecified */ 905 1.1 christos int expected_type; 906 1.1 christos 907 1.1 christos OSSL_LIB_CTX *libctx; 908 1.1 christos char *propq; 909 1.1 christos }; 910 1.1 christos 911 1.1 christos static void OSSL_STORE_LOADER_CTX_free(OSSL_STORE_LOADER_CTX *ctx) 912 1.1 christos { 913 1.1 christos if (ctx == NULL) 914 1.1 christos return; 915 1.1 christos 916 1.1 christos OPENSSL_free(ctx->propq); 917 1.1 christos OPENSSL_free(ctx->uri); 918 1.1 christos if (ctx->type != is_dir) { 919 1.1 christos if (ctx->_.file.last_handler != NULL) { 920 1.1 christos ctx->_.file.last_handler->destroy_ctx(&ctx->_.file.last_handler_ctx); 921 1.1 christos ctx->_.file.last_handler_ctx = NULL; 922 1.1 christos ctx->_.file.last_handler = NULL; 923 1.1 christos } 924 1.1 christos } 925 1.1 christos OPENSSL_free(ctx); 926 1.1 christos } 927 1.1 christos 928 1.1 christos static int file_find_type(OSSL_STORE_LOADER_CTX *ctx) 929 1.1 christos { 930 1.1 christos BIO *buff = NULL; 931 1.1.1.2 christos char peekbuf[4096] = { 932 1.1.1.2 christos 0, 933 1.1.1.2 christos }; 934 1.1 christos 935 1.1 christos if ((buff = BIO_new(BIO_f_buffer())) == NULL) 936 1.1 christos return 0; 937 1.1 christos 938 1.1 christos ctx->_.file.file = BIO_push(buff, ctx->_.file.file); 939 1.1 christos if (BIO_buffer_peek(ctx->_.file.file, peekbuf, sizeof(peekbuf) - 1) > 0) { 940 1.1 christos peekbuf[sizeof(peekbuf) - 1] = '\0'; 941 1.1 christos if (strstr(peekbuf, "-----BEGIN ") != NULL) 942 1.1 christos ctx->type = is_pem; 943 1.1 christos } 944 1.1 christos return 1; 945 1.1 christos } 946 1.1 christos 947 1.1.1.2 christos static OSSL_STORE_LOADER_CTX *file_open_ex(const OSSL_STORE_LOADER *loader, const char *uri, 948 1.1.1.2 christos OSSL_LIB_CTX *libctx, const char *propq, 949 1.1.1.2 christos const UI_METHOD *ui_method, void *ui_data) 950 1.1 christos { 951 1.1 christos OSSL_STORE_LOADER_CTX *ctx = NULL; 952 1.1 christos struct stat st; 953 1.1 christos struct { 954 1.1 christos const char *path; 955 1.1.1.2 christos unsigned int check_absolute : 1; 956 1.1 christos } path_data[2]; 957 1.1 christos size_t path_data_n = 0, i; 958 1.1 christos const char *path, *p = uri, *q; 959 1.1 christos 960 1.1 christos /* 961 1.1 christos * First step, just take the URI as is. 962 1.1 christos */ 963 1.1 christos path_data[path_data_n].check_absolute = 0; 964 1.1 christos path_data[path_data_n++].path = uri; 965 1.1 christos 966 1.1 christos /* 967 1.1 christos * Second step, if the URI appears to start with the "file" scheme, 968 1.1 christos * extract the path and make that the second path to check. 969 1.1 christos * There's a special case if the URI also contains an authority, then 970 1.1 christos * the full URI shouldn't be used as a path anywhere. 971 1.1 christos */ 972 1.1 christos if (CHECK_AND_SKIP_CASE_PREFIX(p, "file:")) { 973 1.1 christos q = p; 974 1.1 christos if (CHECK_AND_SKIP_PREFIX(q, "//")) { 975 1.1.1.2 christos path_data_n--; /* Invalidate using the full URI */ 976 1.1 christos if (CHECK_AND_SKIP_CASE_PREFIX(q, "localhost/") 977 1.1.1.2 christos || CHECK_AND_SKIP_PREFIX(q, "/")) { 978 1.1 christos p = q - 1; 979 1.1 christos } else { 980 1.1 christos ATTICerr(0, ATTIC_R_URI_AUTHORITY_UNSUPPORTED); 981 1.1 christos return NULL; 982 1.1 christos } 983 1.1 christos } 984 1.1 christos 985 1.1 christos path_data[path_data_n].check_absolute = 1; 986 1.1 christos #ifdef _WIN32 987 1.1 christos /* Windows "file:" URIs with a drive letter start with a '/' */ 988 1.1 christos if (p[0] == '/' && p[2] == ':' && p[3] == '/') { 989 1.1 christos char c = tolower((unsigned char)p[1]); 990 1.1 christos 991 1.1 christos if (c >= 'a' && c <= 'z') { 992 1.1 christos p++; 993 1.1 christos /* We know it's absolute, so no need to check */ 994 1.1 christos path_data[path_data_n].check_absolute = 0; 995 1.1 christos } 996 1.1 christos } 997 1.1 christos #endif 998 1.1 christos path_data[path_data_n++].path = p; 999 1.1 christos } 1000 1.1 christos 1001 1.1 christos for (i = 0, path = NULL; path == NULL && i < path_data_n; i++) { 1002 1.1 christos /* 1003 1.1 christos * If the scheme "file" was an explicit part of the URI, the path must 1004 1.1 christos * be absolute. So says RFC 8089 1005 1.1 christos */ 1006 1.1 christos if (path_data[i].check_absolute && path_data[i].path[0] != '/') { 1007 1.1 christos ATTICerr(0, ATTIC_R_PATH_MUST_BE_ABSOLUTE); 1008 1.1 christos ERR_add_error_data(1, path_data[i].path); 1009 1.1 christos return NULL; 1010 1.1 christos } 1011 1.1 christos 1012 1.1 christos if (stat(path_data[i].path, &st) < 0) { 1013 1.1 christos ERR_raise_data(ERR_LIB_SYS, errno, 1014 1.1.1.2 christos "calling stat(%s)", 1015 1.1.1.2 christos path_data[i].path); 1016 1.1 christos } else { 1017 1.1 christos path = path_data[i].path; 1018 1.1 christos } 1019 1.1 christos } 1020 1.1 christos if (path == NULL) { 1021 1.1 christos return NULL; 1022 1.1 christos } 1023 1.1 christos 1024 1.1 christos /* Successfully found a working path */ 1025 1.1 christos 1026 1.1 christos ctx = OPENSSL_zalloc(sizeof(*ctx)); 1027 1.1 christos if (ctx == NULL) 1028 1.1 christos return NULL; 1029 1.1 christos ctx->uri = OPENSSL_strdup(uri); 1030 1.1 christos if (ctx->uri == NULL) 1031 1.1 christos goto err; 1032 1.1 christos 1033 1.1 christos if (S_ISDIR(st.st_mode)) { 1034 1.1 christos ctx->type = is_dir; 1035 1.1 christos ctx->_.dir.last_entry = OPENSSL_DIR_read(&ctx->_.dir.ctx, path); 1036 1.1 christos ctx->_.dir.last_errno = errno; 1037 1.1 christos if (ctx->_.dir.last_entry == NULL) { 1038 1.1 christos if (ctx->_.dir.last_errno != 0) { 1039 1.1 christos ERR_raise(ERR_LIB_SYS, ctx->_.dir.last_errno); 1040 1.1 christos goto err; 1041 1.1 christos } 1042 1.1 christos ctx->_.dir.end_reached = 1; 1043 1.1 christos } 1044 1.1 christos } else if ((ctx->_.file.file = BIO_new_file(path, "rb")) == NULL 1045 1.1.1.2 christos || !file_find_type(ctx)) { 1046 1.1 christos BIO_free_all(ctx->_.file.file); 1047 1.1 christos goto err; 1048 1.1 christos } 1049 1.1 christos if (propq != NULL) { 1050 1.1 christos ctx->propq = OPENSSL_strdup(propq); 1051 1.1 christos if (ctx->propq == NULL) 1052 1.1 christos goto err; 1053 1.1 christos } 1054 1.1 christos ctx->libctx = libctx; 1055 1.1 christos 1056 1.1 christos return ctx; 1057 1.1.1.2 christos err: 1058 1.1 christos OSSL_STORE_LOADER_CTX_free(ctx); 1059 1.1 christos return NULL; 1060 1.1 christos } 1061 1.1 christos 1062 1.1.1.2 christos static OSSL_STORE_LOADER_CTX *file_open(const OSSL_STORE_LOADER *loader, const char *uri, 1063 1.1.1.2 christos const UI_METHOD *ui_method, void *ui_data) 1064 1.1 christos { 1065 1.1 christos return file_open_ex(loader, uri, NULL, NULL, ui_method, ui_data); 1066 1.1 christos } 1067 1.1 christos 1068 1.1.1.2 christos static OSSL_STORE_LOADER_CTX *file_attach(const OSSL_STORE_LOADER *loader, BIO *bp, 1069 1.1.1.2 christos OSSL_LIB_CTX *libctx, const char *propq, 1070 1.1.1.2 christos const UI_METHOD *ui_method, void *ui_data) 1071 1.1 christos { 1072 1.1 christos OSSL_STORE_LOADER_CTX *ctx = NULL; 1073 1.1 christos 1074 1.1 christos if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL 1075 1.1 christos || (propq != NULL && (ctx->propq = OPENSSL_strdup(propq)) == NULL)) { 1076 1.1 christos OSSL_STORE_LOADER_CTX_free(ctx); 1077 1.1 christos return NULL; 1078 1.1 christos } 1079 1.1 christos ctx->libctx = libctx; 1080 1.1 christos ctx->flags |= FILE_FLAG_ATTACHED; 1081 1.1 christos ctx->_.file.file = bp; 1082 1.1 christos if (!file_find_type(ctx)) { 1083 1.1 christos /* Safety measure */ 1084 1.1 christos ctx->_.file.file = NULL; 1085 1.1 christos goto err; 1086 1.1 christos } 1087 1.1 christos return ctx; 1088 1.1 christos err: 1089 1.1 christos OSSL_STORE_LOADER_CTX_free(ctx); 1090 1.1 christos return NULL; 1091 1.1 christos } 1092 1.1 christos 1093 1.1 christos static int file_ctrl(OSSL_STORE_LOADER_CTX *ctx, int cmd, va_list args) 1094 1.1 christos { 1095 1.1 christos int ret = 1; 1096 1.1 christos 1097 1.1 christos switch (cmd) { 1098 1.1.1.2 christos case OSSL_STORE_C_USE_SECMEM: { 1099 1.1.1.2 christos int on = *(va_arg(args, int *)); 1100 1.1.1.2 christos 1101 1.1.1.2 christos switch (on) { 1102 1.1.1.2 christos case 0: 1103 1.1.1.2 christos ctx->flags &= ~FILE_FLAG_SECMEM; 1104 1.1.1.2 christos break; 1105 1.1.1.2 christos case 1: 1106 1.1.1.2 christos ctx->flags |= FILE_FLAG_SECMEM; 1107 1.1.1.2 christos break; 1108 1.1.1.2 christos default: 1109 1.1.1.2 christos ATTICerr(0, ERR_R_PASSED_INVALID_ARGUMENT); 1110 1.1.1.2 christos ret = 0; 1111 1.1.1.2 christos break; 1112 1.1 christos } 1113 1.1.1.2 christos } break; 1114 1.1 christos default: 1115 1.1 christos break; 1116 1.1 christos } 1117 1.1 christos 1118 1.1 christos return ret; 1119 1.1 christos } 1120 1.1 christos 1121 1.1 christos static int file_expect(OSSL_STORE_LOADER_CTX *ctx, int expected) 1122 1.1 christos { 1123 1.1 christos ctx->expected_type = expected; 1124 1.1 christos return 1; 1125 1.1 christos } 1126 1.1 christos 1127 1.1 christos static int file_find(OSSL_STORE_LOADER_CTX *ctx, 1128 1.1.1.2 christos const OSSL_STORE_SEARCH *search) 1129 1.1 christos { 1130 1.1 christos /* 1131 1.1 christos * If ctx == NULL, the library is looking to know if this loader supports 1132 1.1 christos * the given search type. 1133 1.1 christos */ 1134 1.1 christos 1135 1.1 christos if (OSSL_STORE_SEARCH_get_type(search) == OSSL_STORE_SEARCH_BY_NAME) { 1136 1.1 christos unsigned long hash = 0; 1137 1.1 christos 1138 1.1 christos if (ctx == NULL) 1139 1.1 christos return 1; 1140 1.1 christos 1141 1.1 christos if (ctx->type != is_dir) { 1142 1.1 christos ATTICerr(0, ATTIC_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES); 1143 1.1 christos return 0; 1144 1.1 christos } 1145 1.1 christos 1146 1.1 christos hash = X509_NAME_hash_ex(OSSL_STORE_SEARCH_get0_name(search), 1147 1.1.1.2 christos NULL, NULL, NULL); 1148 1.1 christos BIO_snprintf(ctx->_.dir.search_name, sizeof(ctx->_.dir.search_name), 1149 1.1.1.2 christos "%08lx", hash); 1150 1.1 christos return 1; 1151 1.1 christos } 1152 1.1 christos 1153 1.1 christos if (ctx != NULL) 1154 1.1 christos ATTICerr(0, ATTIC_R_UNSUPPORTED_SEARCH_TYPE); 1155 1.1 christos return 0; 1156 1.1 christos } 1157 1.1 christos 1158 1.1 christos static OSSL_STORE_INFO *file_load_try_decode(OSSL_STORE_LOADER_CTX *ctx, 1159 1.1.1.2 christos const char *pem_name, 1160 1.1.1.2 christos const char *pem_header, 1161 1.1.1.2 christos unsigned char *data, size_t len, 1162 1.1.1.2 christos const UI_METHOD *ui_method, 1163 1.1.1.2 christos void *ui_data, int *matchcount) 1164 1.1 christos { 1165 1.1 christos OSSL_STORE_INFO *result = NULL; 1166 1.1 christos BUF_MEM *new_mem = NULL; 1167 1.1 christos char *new_pem_name = NULL; 1168 1.1 christos int t = 0; 1169 1.1 christos 1170 1.1.1.2 christos again: { 1171 1.1.1.2 christos size_t i = 0; 1172 1.1.1.2 christos void *handler_ctx = NULL; 1173 1.1.1.2 christos const FILE_HANDLER **matching_handlers = OPENSSL_zalloc(sizeof(*matching_handlers) 1174 1.1.1.2 christos * OSSL_NELEM(file_handlers)); 1175 1.1 christos 1176 1.1.1.2 christos if (matching_handlers == NULL) 1177 1.1.1.2 christos goto err; 1178 1.1 christos 1179 1.1.1.2 christos *matchcount = 0; 1180 1.1.1.2 christos for (i = 0; i < OSSL_NELEM(file_handlers); i++) { 1181 1.1.1.2 christos const FILE_HANDLER *handler = file_handlers[i]; 1182 1.1.1.2 christos int try_matchcount = 0; 1183 1.1.1.2 christos void *tmp_handler_ctx = NULL; 1184 1.1.1.2 christos OSSL_STORE_INFO *tmp_result; 1185 1.1.1.2 christos unsigned long err; 1186 1.1.1.2 christos 1187 1.1.1.2 christos ERR_set_mark(); 1188 1.1.1.2 christos tmp_result = handler->try_decode(pem_name, pem_header, data, len, 1189 1.1.1.2 christos &tmp_handler_ctx, &try_matchcount, 1190 1.1.1.2 christos ui_method, ui_data, ctx->uri, 1191 1.1.1.2 christos ctx->libctx, ctx->propq); 1192 1.1.1.2 christos /* avoid flooding error queue with low-level ASN.1 parse errors */ 1193 1.1.1.2 christos err = ERR_peek_last_error(); 1194 1.1.1.2 christos if (ERR_GET_LIB(err) == ERR_LIB_ASN1 1195 1.1.1.2 christos && ERR_GET_REASON(err) == ERR_R_NESTED_ASN1_ERROR) 1196 1.1.1.2 christos ERR_pop_to_mark(); 1197 1.1.1.2 christos else 1198 1.1.1.2 christos ERR_clear_last_mark(); 1199 1.1 christos 1200 1.1.1.2 christos if (try_matchcount > 0) { 1201 1.1 christos 1202 1.1.1.2 christos matching_handlers[*matchcount] = handler; 1203 1.1 christos 1204 1.1.1.2 christos if (handler_ctx) 1205 1.1.1.2 christos handler->destroy_ctx(&handler_ctx); 1206 1.1.1.2 christos handler_ctx = tmp_handler_ctx; 1207 1.1 christos 1208 1.1.1.2 christos if ((*matchcount += try_matchcount) > 1) { 1209 1.1.1.2 christos /* more than one match => ambiguous, kill any result */ 1210 1.1.1.2 christos store_info_free(result); 1211 1.1.1.2 christos store_info_free(tmp_result); 1212 1.1.1.2 christos if (handler->destroy_ctx != NULL) 1213 1.1.1.2 christos handler->destroy_ctx(&handler_ctx); 1214 1.1.1.2 christos handler_ctx = NULL; 1215 1.1.1.2 christos tmp_result = NULL; 1216 1.1.1.2 christos result = NULL; 1217 1.1 christos } 1218 1.1.1.2 christos if (result == NULL) 1219 1.1.1.2 christos result = tmp_result; 1220 1.1.1.2 christos if (result == NULL) /* e.g., PKCS#12 file decryption error */ 1221 1.1.1.2 christos break; 1222 1.1 christos } 1223 1.1.1.2 christos } 1224 1.1 christos 1225 1.1.1.2 christos if (result != NULL 1226 1.1.1.2 christos && *matchcount == 1 && matching_handlers[0]->repeatable) { 1227 1.1.1.2 christos ctx->_.file.last_handler = matching_handlers[0]; 1228 1.1.1.2 christos ctx->_.file.last_handler_ctx = handler_ctx; 1229 1.1 christos } 1230 1.1 christos 1231 1.1.1.2 christos OPENSSL_free(matching_handlers); 1232 1.1.1.2 christos } 1233 1.1.1.2 christos 1234 1.1.1.2 christos err: 1235 1.1 christos OPENSSL_free(new_pem_name); 1236 1.1 christos BUF_MEM_free(new_mem); 1237 1.1 christos 1238 1.1 christos if (result != NULL 1239 1.1 christos && (t = OSSL_STORE_INFO_get_type(result)) == STORE_INFO_EMBEDDED) { 1240 1.1 christos struct embedded_st *embedded = get0_EMBEDDED(result); 1241 1.1 christos 1242 1.1 christos /* "steal" the embedded data */ 1243 1.1 christos pem_name = new_pem_name = embedded->pem_name; 1244 1.1 christos new_mem = embedded->blob; 1245 1.1 christos data = (unsigned char *)new_mem->data; 1246 1.1 christos len = new_mem->length; 1247 1.1 christos embedded->pem_name = NULL; 1248 1.1 christos embedded->blob = NULL; 1249 1.1 christos 1250 1.1 christos store_info_free(result); 1251 1.1 christos result = NULL; 1252 1.1 christos goto again; 1253 1.1 christos } 1254 1.1 christos 1255 1.1 christos return result; 1256 1.1 christos } 1257 1.1 christos 1258 1.1 christos static OSSL_STORE_INFO *file_load_try_repeat(OSSL_STORE_LOADER_CTX *ctx, 1259 1.1.1.2 christos const UI_METHOD *ui_method, 1260 1.1.1.2 christos void *ui_data) 1261 1.1 christos { 1262 1.1 christos OSSL_STORE_INFO *result = NULL; 1263 1.1 christos int try_matchcount = 0; 1264 1.1 christos 1265 1.1 christos if (ctx->_.file.last_handler != NULL) { 1266 1.1.1.2 christos result = ctx->_.file.last_handler->try_decode(NULL, NULL, NULL, 0, 1267 1.1.1.2 christos &ctx->_.file.last_handler_ctx, 1268 1.1.1.2 christos &try_matchcount, 1269 1.1.1.2 christos ui_method, ui_data, ctx->uri, 1270 1.1.1.2 christos ctx->libctx, ctx->propq); 1271 1.1 christos 1272 1.1 christos if (result == NULL) { 1273 1.1 christos ctx->_.file.last_handler->destroy_ctx(&ctx->_.file.last_handler_ctx); 1274 1.1 christos ctx->_.file.last_handler_ctx = NULL; 1275 1.1 christos ctx->_.file.last_handler = NULL; 1276 1.1 christos } 1277 1.1 christos } 1278 1.1 christos return result; 1279 1.1 christos } 1280 1.1 christos 1281 1.1 christos static void pem_free_flag(void *pem_data, int secure, size_t num) 1282 1.1 christos { 1283 1.1 christos if (secure) 1284 1.1 christos OPENSSL_secure_clear_free(pem_data, num); 1285 1.1 christos else 1286 1.1 christos OPENSSL_free(pem_data); 1287 1.1 christos } 1288 1.1 christos static int file_read_pem(BIO *bp, char **pem_name, char **pem_header, 1289 1.1.1.2 christos unsigned char **data, long *len, 1290 1.1.1.2 christos const UI_METHOD *ui_method, void *ui_data, 1291 1.1.1.2 christos const char *uri, int secure) 1292 1.1 christos { 1293 1.1 christos int i = secure 1294 1.1 christos ? PEM_read_bio_ex(bp, pem_name, pem_header, data, len, 1295 1.1.1.2 christos PEM_FLAG_SECURE | PEM_FLAG_EAY_COMPATIBLE) 1296 1.1 christos : PEM_read_bio(bp, pem_name, pem_header, data, len); 1297 1.1 christos 1298 1.1 christos if (i <= 0) 1299 1.1 christos return 0; 1300 1.1 christos 1301 1.1 christos /* 1302 1.1 christos * 10 is the number of characters in "Proc-Type:", which 1303 1.1 christos * PEM_get_EVP_CIPHER_INFO() requires to be present. 1304 1.1 christos * If the PEM header has less characters than that, it's 1305 1.1 christos * not worth spending cycles on it. 1306 1.1 christos */ 1307 1.1 christos if (strlen(*pem_header) > 10) { 1308 1.1 christos EVP_CIPHER_INFO cipher; 1309 1.1 christos struct pem_pass_data pass_data; 1310 1.1 christos 1311 1.1 christos if (!PEM_get_EVP_CIPHER_INFO(*pem_header, &cipher) 1312 1.1 christos || !file_fill_pem_pass_data(&pass_data, "PEM pass phrase", uri, 1313 1.1.1.2 christos ui_method, ui_data) 1314 1.1 christos || !PEM_do_header(&cipher, *data, len, file_get_pem_pass, 1315 1.1.1.2 christos &pass_data)) { 1316 1.1 christos return 0; 1317 1.1 christos } 1318 1.1 christos } 1319 1.1 christos return 1; 1320 1.1 christos } 1321 1.1 christos 1322 1.1 christos static OSSL_STORE_INFO *file_try_read_msblob(BIO *bp, int *matchcount) 1323 1.1 christos { 1324 1.1 christos OSSL_STORE_INFO *result = NULL; 1325 1.1 christos int ispub = -1; 1326 1.1 christos 1327 1.1 christos { 1328 1.1 christos unsigned int magic = 0, bitlen = 0; 1329 1.1 christos int isdss = 0; 1330 1.1.1.2 christos unsigned char peekbuf[16] = { 1331 1.1.1.2 christos 0, 1332 1.1.1.2 christos }; 1333 1.1 christos const unsigned char *p = peekbuf; 1334 1.1 christos 1335 1.1 christos if (BIO_buffer_peek(bp, peekbuf, sizeof(peekbuf)) <= 0) 1336 1.1 christos return 0; 1337 1.1 christos if (ossl_do_blob_header(&p, sizeof(peekbuf), &magic, &bitlen, 1338 1.1.1.2 christos &isdss, &ispub) 1339 1.1.1.2 christos <= 0) 1340 1.1 christos return 0; 1341 1.1 christos } 1342 1.1 christos 1343 1.1 christos (*matchcount)++; 1344 1.1 christos 1345 1.1 christos { 1346 1.1 christos EVP_PKEY *tmp = ispub 1347 1.1 christos ? b2i_PublicKey_bio(bp) 1348 1.1 christos : b2i_PrivateKey_bio(bp); 1349 1.1 christos 1350 1.1 christos if (tmp == NULL 1351 1.1 christos || (result = OSSL_STORE_INFO_new_PKEY(tmp)) == NULL) { 1352 1.1 christos EVP_PKEY_free(tmp); 1353 1.1 christos return 0; 1354 1.1 christos } 1355 1.1 christos } 1356 1.1 christos 1357 1.1 christos return result; 1358 1.1 christos } 1359 1.1 christos 1360 1.1 christos static OSSL_STORE_INFO *file_try_read_PVK(BIO *bp, const UI_METHOD *ui_method, 1361 1.1.1.2 christos void *ui_data, const char *uri, 1362 1.1.1.2 christos int *matchcount) 1363 1.1 christos { 1364 1.1 christos OSSL_STORE_INFO *result = NULL; 1365 1.1 christos 1366 1.1 christos { 1367 1.1 christos unsigned int saltlen = 0, keylen = 0; 1368 1.1 christos int isdss = -1; 1369 1.1.1.2 christos unsigned char peekbuf[24] = { 1370 1.1.1.2 christos 0, 1371 1.1.1.2 christos }; 1372 1.1 christos const unsigned char *p = peekbuf; 1373 1.1 christos 1374 1.1 christos if (BIO_buffer_peek(bp, peekbuf, sizeof(peekbuf)) <= 0) 1375 1.1 christos return 0; 1376 1.1 christos if (!ossl_do_PVK_header(&p, sizeof(peekbuf), 0, &isdss, &saltlen, &keylen)) 1377 1.1 christos return 0; 1378 1.1 christos } 1379 1.1 christos 1380 1.1 christos (*matchcount)++; 1381 1.1 christos 1382 1.1 christos { 1383 1.1 christos EVP_PKEY *tmp = NULL; 1384 1.1 christos struct pem_pass_data pass_data; 1385 1.1 christos 1386 1.1 christos if (!file_fill_pem_pass_data(&pass_data, "PVK pass phrase", uri, 1387 1.1.1.2 christos ui_method, ui_data) 1388 1.1 christos || (tmp = b2i_PVK_bio(bp, file_get_pem_pass, &pass_data)) == NULL 1389 1.1 christos || (result = OSSL_STORE_INFO_new_PKEY(tmp)) == NULL) { 1390 1.1 christos EVP_PKEY_free(tmp); 1391 1.1 christos return 0; 1392 1.1 christos } 1393 1.1 christos } 1394 1.1 christos 1395 1.1 christos return result; 1396 1.1 christos } 1397 1.1 christos 1398 1.1 christos static int file_read_asn1(BIO *bp, unsigned char **data, long *len) 1399 1.1 christos { 1400 1.1 christos BUF_MEM *mem = NULL; 1401 1.1 christos 1402 1.1 christos if (asn1_d2i_read_bio(bp, &mem) < 0) 1403 1.1 christos return 0; 1404 1.1 christos 1405 1.1 christos *data = (unsigned char *)mem->data; 1406 1.1 christos *len = (long)mem->length; 1407 1.1 christos OPENSSL_free(mem); 1408 1.1 christos 1409 1.1 christos return 1; 1410 1.1 christos } 1411 1.1 christos 1412 1.1 christos static int file_name_to_uri(OSSL_STORE_LOADER_CTX *ctx, const char *name, 1413 1.1.1.2 christos char **data) 1414 1.1 christos { 1415 1.1 christos assert(name != NULL); 1416 1.1 christos assert(data != NULL); 1417 1.1 christos { 1418 1.1 christos const char *pathsep = ossl_ends_with_dirsep(ctx->uri) ? "" : "/"; 1419 1.1 christos long calculated_length = strlen(ctx->uri) + strlen(pathsep) 1420 1.1 christos + strlen(name) + 1 /* \0 */; 1421 1.1 christos 1422 1.1 christos *data = OPENSSL_zalloc(calculated_length); 1423 1.1 christos if (*data == NULL) 1424 1.1 christos return 0; 1425 1.1 christos 1426 1.1 christos OPENSSL_strlcat(*data, ctx->uri, calculated_length); 1427 1.1 christos OPENSSL_strlcat(*data, pathsep, calculated_length); 1428 1.1 christos OPENSSL_strlcat(*data, name, calculated_length); 1429 1.1 christos } 1430 1.1 christos return 1; 1431 1.1 christos } 1432 1.1 christos 1433 1.1 christos static int file_name_check(OSSL_STORE_LOADER_CTX *ctx, const char *name) 1434 1.1 christos { 1435 1.1 christos const char *p = NULL; 1436 1.1 christos size_t len = strlen(ctx->_.dir.search_name); 1437 1.1 christos 1438 1.1 christos /* If there are no search criteria, all names are accepted */ 1439 1.1 christos if (ctx->_.dir.search_name[0] == '\0') 1440 1.1 christos return 1; 1441 1.1 christos 1442 1.1 christos /* If the expected type isn't supported, no name is accepted */ 1443 1.1 christos if (ctx->expected_type != 0 1444 1.1 christos && ctx->expected_type != OSSL_STORE_INFO_CERT 1445 1.1 christos && ctx->expected_type != OSSL_STORE_INFO_CRL) 1446 1.1 christos return 0; 1447 1.1 christos 1448 1.1 christos /* 1449 1.1 christos * First, check the basename 1450 1.1 christos */ 1451 1.1 christos if (OPENSSL_strncasecmp(name, ctx->_.dir.search_name, len) != 0 1452 1.1 christos || name[len] != '.') 1453 1.1 christos return 0; 1454 1.1 christos p = &name[len + 1]; 1455 1.1 christos 1456 1.1 christos /* 1457 1.1 christos * Then, if the expected type is a CRL, check that the extension starts 1458 1.1 christos * with 'r' 1459 1.1 christos */ 1460 1.1 christos if (*p == 'r') { 1461 1.1 christos p++; 1462 1.1 christos if (ctx->expected_type != 0 1463 1.1 christos && ctx->expected_type != OSSL_STORE_INFO_CRL) 1464 1.1 christos return 0; 1465 1.1 christos } else if (ctx->expected_type == OSSL_STORE_INFO_CRL) { 1466 1.1 christos return 0; 1467 1.1 christos } 1468 1.1 christos 1469 1.1 christos /* 1470 1.1 christos * Last, check that the rest of the extension is a decimal number, at 1471 1.1 christos * least one digit long. 1472 1.1 christos */ 1473 1.1 christos if (!isdigit((unsigned char)*p)) 1474 1.1 christos return 0; 1475 1.1 christos while (isdigit((unsigned char)*p)) 1476 1.1 christos p++; 1477 1.1 christos 1478 1.1 christos #ifdef __VMS 1479 1.1 christos /* 1480 1.1 christos * One extra step here, check for a possible generation number. 1481 1.1 christos */ 1482 1.1 christos if (*p == ';') 1483 1.1 christos for (p++; *p != '\0'; p++) 1484 1.1 christos if (!ossl_isdigit(*p)) 1485 1.1 christos break; 1486 1.1 christos #endif 1487 1.1 christos 1488 1.1 christos /* 1489 1.1 christos * If we've reached the end of the string at this point, we've successfully 1490 1.1 christos * found a fitting file name. 1491 1.1 christos */ 1492 1.1 christos return *p == '\0'; 1493 1.1 christos } 1494 1.1 christos 1495 1.1 christos static int file_eof(OSSL_STORE_LOADER_CTX *ctx); 1496 1.1 christos static int file_error(OSSL_STORE_LOADER_CTX *ctx); 1497 1.1 christos static OSSL_STORE_INFO *file_load(OSSL_STORE_LOADER_CTX *ctx, 1498 1.1.1.2 christos const UI_METHOD *ui_method, 1499 1.1.1.2 christos void *ui_data) 1500 1.1 christos { 1501 1.1 christos OSSL_STORE_INFO *result = NULL; 1502 1.1 christos 1503 1.1 christos ctx->errcnt = 0; 1504 1.1 christos 1505 1.1 christos if (ctx->type == is_dir) { 1506 1.1 christos do { 1507 1.1 christos char *newname = NULL; 1508 1.1 christos 1509 1.1 christos if (ctx->_.dir.last_entry == NULL) { 1510 1.1 christos if (!ctx->_.dir.end_reached) { 1511 1.1 christos assert(ctx->_.dir.last_errno != 0); 1512 1.1 christos ERR_raise(ERR_LIB_SYS, ctx->_.dir.last_errno); 1513 1.1 christos ctx->errcnt++; 1514 1.1 christos } 1515 1.1 christos return NULL; 1516 1.1 christos } 1517 1.1 christos 1518 1.1 christos if (ctx->_.dir.last_entry[0] != '.' 1519 1.1 christos && file_name_check(ctx, ctx->_.dir.last_entry) 1520 1.1 christos && !file_name_to_uri(ctx, ctx->_.dir.last_entry, &newname)) 1521 1.1 christos return NULL; 1522 1.1 christos 1523 1.1 christos /* 1524 1.1 christos * On the first call (with a NULL context), OPENSSL_DIR_read() 1525 1.1 christos * cares about the second argument. On the following calls, it 1526 1.1 christos * only cares that it isn't NULL. Therefore, we can safely give 1527 1.1 christos * it our URI here. 1528 1.1 christos */ 1529 1.1 christos ctx->_.dir.last_entry = OPENSSL_DIR_read(&ctx->_.dir.ctx, ctx->uri); 1530 1.1 christos ctx->_.dir.last_errno = errno; 1531 1.1 christos if (ctx->_.dir.last_entry == NULL && ctx->_.dir.last_errno == 0) 1532 1.1 christos ctx->_.dir.end_reached = 1; 1533 1.1 christos 1534 1.1 christos if (newname != NULL 1535 1.1 christos && (result = OSSL_STORE_INFO_new_NAME(newname)) == NULL) { 1536 1.1 christos OPENSSL_free(newname); 1537 1.1 christos ATTICerr(0, ERR_R_OSSL_STORE_LIB); 1538 1.1 christos return NULL; 1539 1.1 christos } 1540 1.1 christos } while (result == NULL && !file_eof(ctx)); 1541 1.1 christos } else { 1542 1.1 christos int matchcount = -1; 1543 1.1 christos 1544 1.1.1.2 christos again: 1545 1.1 christos result = file_load_try_repeat(ctx, ui_method, ui_data); 1546 1.1 christos if (result != NULL) 1547 1.1 christos return result; 1548 1.1 christos 1549 1.1 christos if (file_eof(ctx)) 1550 1.1 christos return NULL; 1551 1.1 christos 1552 1.1 christos do { 1553 1.1.1.2 christos char *pem_name = NULL; /* PEM record name */ 1554 1.1.1.2 christos char *pem_header = NULL; /* PEM record header */ 1555 1.1 christos unsigned char *data = NULL; /* DER encoded data */ 1556 1.1.1.2 christos long len = 0; /* DER encoded data length */ 1557 1.1 christos 1558 1.1 christos matchcount = -1; 1559 1.1 christos if (ctx->type == is_pem) { 1560 1.1 christos if (!file_read_pem(ctx->_.file.file, &pem_name, &pem_header, 1561 1.1.1.2 christos &data, &len, ui_method, ui_data, ctx->uri, 1562 1.1.1.2 christos (ctx->flags & FILE_FLAG_SECMEM) != 0)) { 1563 1.1 christos ctx->errcnt++; 1564 1.1 christos goto endloop; 1565 1.1 christos } 1566 1.1 christos } else { 1567 1.1 christos if ((result = file_try_read_msblob(ctx->_.file.file, 1568 1.1.1.2 christos &matchcount)) 1569 1.1.1.2 christos != NULL 1570 1.1 christos || (result = file_try_read_PVK(ctx->_.file.file, 1571 1.1.1.2 christos ui_method, ui_data, ctx->uri, 1572 1.1.1.2 christos &matchcount)) 1573 1.1.1.2 christos != NULL) 1574 1.1 christos goto endloop; 1575 1.1 christos 1576 1.1 christos if (!file_read_asn1(ctx->_.file.file, &data, &len)) { 1577 1.1 christos ctx->errcnt++; 1578 1.1 christos goto endloop; 1579 1.1 christos } 1580 1.1 christos } 1581 1.1 christos 1582 1.1 christos result = file_load_try_decode(ctx, pem_name, pem_header, data, len, 1583 1.1.1.2 christos ui_method, ui_data, &matchcount); 1584 1.1 christos 1585 1.1 christos if (result != NULL) 1586 1.1 christos goto endloop; 1587 1.1 christos 1588 1.1 christos /* 1589 1.1 christos * If a PEM name matches more than one handler, the handlers are 1590 1.1 christos * badly coded. 1591 1.1 christos */ 1592 1.1 christos if (!ossl_assert(pem_name == NULL || matchcount <= 1)) { 1593 1.1 christos ctx->errcnt++; 1594 1.1 christos goto endloop; 1595 1.1 christos } 1596 1.1 christos 1597 1.1 christos if (matchcount > 1) { 1598 1.1 christos ATTICerr(0, ATTIC_R_AMBIGUOUS_CONTENT_TYPE); 1599 1.1 christos } else if (matchcount == 1) { 1600 1.1 christos /* 1601 1.1 christos * If there are other errors on the stack, they already show 1602 1.1 christos * what the problem is. 1603 1.1 christos */ 1604 1.1 christos if (ERR_peek_error() == 0) { 1605 1.1 christos ATTICerr(0, ATTIC_R_UNSUPPORTED_CONTENT_TYPE); 1606 1.1 christos if (pem_name != NULL) 1607 1.1 christos ERR_add_error_data(3, "PEM type is '", pem_name, "'"); 1608 1.1 christos } 1609 1.1 christos } 1610 1.1 christos if (matchcount > 0) 1611 1.1 christos ctx->errcnt++; 1612 1.1 christos 1613 1.1.1.2 christos endloop: 1614 1.1 christos pem_free_flag(pem_name, (ctx->flags & FILE_FLAG_SECMEM) != 0, 0); 1615 1.1 christos pem_free_flag(pem_header, (ctx->flags & FILE_FLAG_SECMEM) != 0, 0); 1616 1.1 christos pem_free_flag(data, (ctx->flags & FILE_FLAG_SECMEM) != 0, len); 1617 1.1 christos } while (matchcount == 0 && !file_eof(ctx) && !file_error(ctx)); 1618 1.1 christos 1619 1.1 christos /* We bail out on ambiguity */ 1620 1.1 christos if (matchcount > 1) { 1621 1.1 christos store_info_free(result); 1622 1.1 christos return NULL; 1623 1.1 christos } 1624 1.1 christos 1625 1.1 christos if (result != NULL 1626 1.1 christos && ctx->expected_type != 0 1627 1.1 christos && ctx->expected_type != OSSL_STORE_INFO_get_type(result)) { 1628 1.1 christos store_info_free(result); 1629 1.1 christos goto again; 1630 1.1 christos } 1631 1.1 christos } 1632 1.1 christos 1633 1.1 christos return result; 1634 1.1 christos } 1635 1.1 christos 1636 1.1 christos static int file_error(OSSL_STORE_LOADER_CTX *ctx) 1637 1.1 christos { 1638 1.1 christos return ctx->errcnt > 0; 1639 1.1 christos } 1640 1.1 christos 1641 1.1 christos static int file_eof(OSSL_STORE_LOADER_CTX *ctx) 1642 1.1 christos { 1643 1.1 christos if (ctx->type == is_dir) 1644 1.1 christos return ctx->_.dir.end_reached; 1645 1.1 christos 1646 1.1 christos if (ctx->_.file.last_handler != NULL 1647 1.1 christos && !ctx->_.file.last_handler->eof(ctx->_.file.last_handler_ctx)) 1648 1.1 christos return 0; 1649 1.1 christos return BIO_eof(ctx->_.file.file); 1650 1.1 christos } 1651 1.1 christos 1652 1.1 christos static int file_close(OSSL_STORE_LOADER_CTX *ctx) 1653 1.1 christos { 1654 1.1 christos if ((ctx->flags & FILE_FLAG_ATTACHED) == 0) { 1655 1.1 christos if (ctx->type == is_dir) 1656 1.1 christos OPENSSL_DIR_end(&ctx->_.dir.ctx); 1657 1.1 christos else 1658 1.1 christos BIO_free_all(ctx->_.file.file); 1659 1.1 christos } else { 1660 1.1 christos /* 1661 1.1 christos * Because file_attach() called file_find_type(), we know that a 1662 1.1 christos * BIO_f_buffer() has been pushed on top of the regular BIO. 1663 1.1 christos */ 1664 1.1 christos BIO *buff = ctx->_.file.file; 1665 1.1 christos 1666 1.1 christos /* Detach buff */ 1667 1.1 christos (void)BIO_pop(ctx->_.file.file); 1668 1.1 christos /* Safety measure */ 1669 1.1 christos ctx->_.file.file = NULL; 1670 1.1 christos 1671 1.1 christos BIO_free(buff); 1672 1.1 christos } 1673 1.1 christos OSSL_STORE_LOADER_CTX_free(ctx); 1674 1.1 christos return 1; 1675 1.1 christos } 1676 1.1 christos 1677 1.1 christos /*- 1678 1.1 christos * ENGINE management 1679 1.1 christos */ 1680 1.1 christos 1681 1.1 christos static const char *loader_attic_id = "loader_attic"; 1682 1.1 christos static const char *loader_attic_name = "'file:' loader"; 1683 1.1 christos 1684 1.1 christos static OSSL_STORE_LOADER *loader_attic = NULL; 1685 1.1 christos 1686 1.1 christos static int loader_attic_init(ENGINE *e) 1687 1.1 christos { 1688 1.1 christos return 1; 1689 1.1 christos } 1690 1.1 christos 1691 1.1 christos static int loader_attic_finish(ENGINE *e) 1692 1.1 christos { 1693 1.1 christos return 1; 1694 1.1 christos } 1695 1.1 christos 1696 1.1 christos static int loader_attic_destroy(ENGINE *e) 1697 1.1 christos { 1698 1.1 christos OSSL_STORE_LOADER *loader = OSSL_STORE_unregister_loader("file"); 1699 1.1 christos 1700 1.1 christos if (loader == NULL) 1701 1.1 christos return 0; 1702 1.1 christos 1703 1.1 christos ERR_unload_ATTIC_strings(); 1704 1.1 christos OSSL_STORE_LOADER_free(loader); 1705 1.1 christos return 1; 1706 1.1 christos } 1707 1.1 christos 1708 1.1 christos static int bind_loader_attic(ENGINE *e) 1709 1.1 christos { 1710 1.1 christos 1711 1.1 christos /* Ensure the ATTIC error handling is set up on best effort basis */ 1712 1.1 christos ERR_load_ATTIC_strings(); 1713 1.1 christos 1714 1.1 christos if (/* Create the OSSL_STORE_LOADER */ 1715 1.1 christos (loader_attic = OSSL_STORE_LOADER_new(e, "file")) == NULL 1716 1.1 christos || !OSSL_STORE_LOADER_set_open_ex(loader_attic, file_open_ex) 1717 1.1 christos || !OSSL_STORE_LOADER_set_open(loader_attic, file_open) 1718 1.1 christos || !OSSL_STORE_LOADER_set_attach(loader_attic, file_attach) 1719 1.1 christos || !OSSL_STORE_LOADER_set_ctrl(loader_attic, file_ctrl) 1720 1.1 christos || !OSSL_STORE_LOADER_set_expect(loader_attic, file_expect) 1721 1.1 christos || !OSSL_STORE_LOADER_set_find(loader_attic, file_find) 1722 1.1 christos || !OSSL_STORE_LOADER_set_load(loader_attic, file_load) 1723 1.1 christos || !OSSL_STORE_LOADER_set_eof(loader_attic, file_eof) 1724 1.1 christos || !OSSL_STORE_LOADER_set_error(loader_attic, file_error) 1725 1.1 christos || !OSSL_STORE_LOADER_set_close(loader_attic, file_close) 1726 1.1 christos /* Init the engine itself */ 1727 1.1 christos || !ENGINE_set_id(e, loader_attic_id) 1728 1.1 christos || !ENGINE_set_name(e, loader_attic_name) 1729 1.1 christos || !ENGINE_set_destroy_function(e, loader_attic_destroy) 1730 1.1 christos || !ENGINE_set_init_function(e, loader_attic_init) 1731 1.1 christos || !ENGINE_set_finish_function(e, loader_attic_finish) 1732 1.1 christos /* Finally, register the method with libcrypto */ 1733 1.1 christos || !OSSL_STORE_register_loader(loader_attic)) { 1734 1.1 christos OSSL_STORE_LOADER_free(loader_attic); 1735 1.1 christos loader_attic = NULL; 1736 1.1 christos ATTICerr(0, ATTIC_R_INIT_FAILED); 1737 1.1 christos return 0; 1738 1.1 christos } 1739 1.1 christos 1740 1.1 christos return 1; 1741 1.1 christos } 1742 1.1 christos 1743 1.1 christos #ifdef OPENSSL_NO_DYNAMIC_ENGINE 1744 1.1.1.2 christos #error "Only allowed as dynamically shared object" 1745 1.1 christos #endif 1746 1.1 christos 1747 1.1 christos static int bind_helper(ENGINE *e, const char *id) 1748 1.1 christos { 1749 1.1 christos if (id && (strcmp(id, loader_attic_id) != 0)) 1750 1.1 christos return 0; 1751 1.1 christos if (!bind_loader_attic(e)) 1752 1.1 christos return 0; 1753 1.1 christos return 1; 1754 1.1 christos } 1755 1.1 christos 1756 1.1 christos IMPLEMENT_DYNAMIC_CHECK_FN() 1757 1.1.1.2 christos IMPLEMENT_DYNAMIC_BIND_FN(bind_helper) 1758