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