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 #include <string.h> 11 #include <openssl/asn1t.h> 12 #include <openssl/core_names.h> 13 #include <openssl/core_object.h> 14 #include <openssl/params.h> 15 #include <openssl/x509.h> 16 #include "internal/sizes.h" 17 #include "crypto/x509.h" 18 #include "crypto/ec.h" 19 #include "prov/bio.h" 20 #include "prov/decoders.h" 21 #include "prov/implementations.h" 22 #include "endecoder_local.h" 23 24 static OSSL_FUNC_decoder_newctx_fn spki2typespki_newctx; 25 static OSSL_FUNC_decoder_freectx_fn spki2typespki_freectx; 26 static OSSL_FUNC_decoder_decode_fn spki2typespki_decode; 27 static OSSL_FUNC_decoder_settable_ctx_params_fn spki2typespki_settable_ctx_params; 28 static OSSL_FUNC_decoder_set_ctx_params_fn spki2typespki_set_ctx_params; 29 30 /* 31 * Context used for SubjectPublicKeyInfo to Type specific SubjectPublicKeyInfo 32 * decoding. 33 */ 34 struct spki2typespki_ctx_st { 35 PROV_CTX *provctx; 36 char propq[OSSL_MAX_PROPQUERY_SIZE]; 37 }; 38 39 static void *spki2typespki_newctx(void *provctx) 40 { 41 struct spki2typespki_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx)); 42 43 if (ctx != NULL) 44 ctx->provctx = provctx; 45 return ctx; 46 } 47 48 static void spki2typespki_freectx(void *vctx) 49 { 50 struct spki2typespki_ctx_st *ctx = vctx; 51 52 OPENSSL_free(ctx); 53 } 54 55 static const OSSL_PARAM *spki2typespki_settable_ctx_params(ossl_unused void *provctx) 56 { 57 static const OSSL_PARAM settables[] = { 58 OSSL_PARAM_utf8_string(OSSL_DECODER_PARAM_PROPERTIES, NULL, 0), 59 OSSL_PARAM_END 60 }; 61 return settables; 62 } 63 64 static int spki2typespki_set_ctx_params(void *vctx, const OSSL_PARAM params[]) 65 { 66 struct spki2typespki_ctx_st *ctx = vctx; 67 const OSSL_PARAM *p; 68 char *str = ctx->propq; 69 70 p = OSSL_PARAM_locate_const(params, OSSL_DECODER_PARAM_PROPERTIES); 71 if (p != NULL && !OSSL_PARAM_get_utf8_string(p, &str, sizeof(ctx->propq))) 72 return 0; 73 74 return 1; 75 } 76 77 static int spki2typespki_decode(void *vctx, OSSL_CORE_BIO *cin, int selection, 78 OSSL_CALLBACK *data_cb, void *data_cbarg, 79 OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) 80 { 81 struct spki2typespki_ctx_st *ctx = vctx; 82 unsigned char *der; 83 long len; 84 int ok = 0; 85 86 if (!ossl_read_der(ctx->provctx, cin, &der, &len)) 87 return 1; 88 89 ok = ossl_spki2typespki_der_decode(der, len, selection, data_cb, data_cbarg, 90 pw_cb, pw_cbarg, 91 PROV_LIBCTX_OF(ctx->provctx), ctx->propq); 92 OPENSSL_free(der); 93 return ok; 94 } 95 96 int ossl_spki2typespki_der_decode(unsigned char *der, long len, int selection, 97 OSSL_CALLBACK *data_cb, void *data_cbarg, 98 OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg, 99 OSSL_LIB_CTX *libctx, const char *propq) 100 { 101 const unsigned char *derp = der; 102 X509_PUBKEY *xpub = NULL; 103 X509_ALGOR *algor = NULL; 104 const ASN1_OBJECT *oid = NULL; 105 char dataname[OSSL_MAX_NAME_SIZE]; 106 OSSL_PARAM params[6], *p = params; 107 int objtype = OSSL_OBJECT_PKEY; 108 int ok = 0; 109 110 xpub = ossl_d2i_X509_PUBKEY_INTERNAL(&derp, len, libctx, propq); 111 112 if (xpub == NULL) { 113 /* We return "empty handed". This is not an error. */ 114 ok = 1; 115 goto end; 116 } 117 118 if (!X509_PUBKEY_get0_param(NULL, NULL, NULL, &algor, xpub)) 119 goto end; 120 X509_ALGOR_get0(&oid, NULL, NULL, algor); 121 122 #ifndef OPENSSL_NO_EC 123 /* SM2 abuses the EC oid, so this could actually be SM2 */ 124 if (OBJ_obj2nid(oid) == NID_X9_62_id_ecPublicKey 125 && ossl_x509_algor_is_sm2(algor)) 126 strcpy(dataname, "SM2"); 127 else 128 #endif 129 if (OBJ_obj2txt(dataname, sizeof(dataname), oid, 0) <= 0) 130 goto end; 131 132 ossl_X509_PUBKEY_INTERNAL_free(xpub); 133 xpub = NULL; 134 135 *p++ = OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE, 136 dataname, 0); 137 138 *p++ = OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_INPUT_TYPE, 139 "DER", 0); 140 141 *p++ = OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_STRUCTURE, 142 "SubjectPublicKeyInfo", 143 0); 144 *p++ = OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_DATA, der, len); 145 *p++ = OSSL_PARAM_construct_int(OSSL_OBJECT_PARAM_TYPE, &objtype); 146 147 *p = OSSL_PARAM_construct_end(); 148 149 ok = data_cb(params, data_cbarg); 150 151 end: 152 ossl_X509_PUBKEY_INTERNAL_free(xpub); 153 return ok; 154 } 155 156 const OSSL_DISPATCH ossl_SubjectPublicKeyInfo_der_to_der_decoder_functions[] = { 157 { OSSL_FUNC_DECODER_NEWCTX, (void (*)(void))spki2typespki_newctx }, 158 { OSSL_FUNC_DECODER_FREECTX, (void (*)(void))spki2typespki_freectx }, 159 { OSSL_FUNC_DECODER_DECODE, (void (*)(void))spki2typespki_decode }, 160 { OSSL_FUNC_DECODER_SETTABLE_CTX_PARAMS, 161 (void (*)(void))spki2typespki_settable_ctx_params }, 162 { OSSL_FUNC_DECODER_SET_CTX_PARAMS, 163 (void (*)(void))spki2typespki_set_ctx_params }, 164 OSSL_DISPATCH_END 165 }; 166