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 #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/implementations.h"
21 #include "endecoder_local.h"
22
23 static OSSL_FUNC_decoder_newctx_fn spki2typespki_newctx;
24 static OSSL_FUNC_decoder_freectx_fn spki2typespki_freectx;
25 static OSSL_FUNC_decoder_decode_fn spki2typespki_decode;
26
27 /*
28 * Context used for SubjectPublicKeyInfo to Type specific SubjectPublicKeyInfo
29 * decoding.
30 */
31 struct spki2typespki_ctx_st {
32 PROV_CTX *provctx;
33 };
34
spki2typespki_newctx(void * provctx)35 static void *spki2typespki_newctx(void *provctx)
36 {
37 struct spki2typespki_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx));
38
39 if (ctx != NULL)
40 ctx->provctx = provctx;
41 return ctx;
42 }
43
spki2typespki_freectx(void * vctx)44 static void spki2typespki_freectx(void *vctx)
45 {
46 struct spki2typespki_ctx_st *ctx = vctx;
47
48 OPENSSL_free(ctx);
49 }
50
spki2typespki_decode(void * vctx,OSSL_CORE_BIO * cin,int selection,OSSL_CALLBACK * data_cb,void * data_cbarg,OSSL_PASSPHRASE_CALLBACK * pw_cb,void * pw_cbarg)51 static int spki2typespki_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,
52 OSSL_CALLBACK *data_cb, void *data_cbarg,
53 OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
54 {
55 struct spki2typespki_ctx_st *ctx = vctx;
56 unsigned char *der, *derp;
57 long len;
58 int ok = 0;
59 int objtype = OSSL_OBJECT_PKEY;
60 X509_PUBKEY *xpub = NULL;
61 X509_ALGOR *algor = NULL;
62 const ASN1_OBJECT *oid = NULL;
63 char dataname[OSSL_MAX_NAME_SIZE];
64 OSSL_PARAM params[5], *p = params;
65
66 if (!ossl_read_der(ctx->provctx, cin, &der, &len))
67 return 1;
68 derp = der;
69 xpub = ossl_d2i_X509_PUBKEY_INTERNAL((const unsigned char **)&derp, len,
70 PROV_LIBCTX_OF(ctx->provctx));
71
72
73 if (xpub == NULL) {
74 /* We return "empty handed". This is not an error. */
75 ok = 1;
76 goto end;
77 }
78
79 if (!X509_PUBKEY_get0_param(NULL, NULL, NULL, &algor, xpub))
80 goto end;
81 X509_ALGOR_get0(&oid, NULL, NULL, algor);
82
83 #ifndef OPENSSL_NO_EC
84 /* SM2 abuses the EC oid, so this could actually be SM2 */
85 if (OBJ_obj2nid(oid) == NID_X9_62_id_ecPublicKey
86 && ossl_x509_algor_is_sm2(algor))
87 strcpy(dataname, "SM2");
88 else
89 #endif
90 if (OBJ_obj2txt(dataname, sizeof(dataname), oid, 0) <= 0)
91 goto end;
92
93 ossl_X509_PUBKEY_INTERNAL_free(xpub);
94 xpub = NULL;
95
96 *p++ =
97 OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_TYPE,
98 dataname, 0);
99
100 *p++ =
101 OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_STRUCTURE,
102 "SubjectPublicKeyInfo",
103 0);
104 *p++ =
105 OSSL_PARAM_construct_octet_string(OSSL_OBJECT_PARAM_DATA, der, len);
106 *p++ =
107 OSSL_PARAM_construct_int(OSSL_OBJECT_PARAM_TYPE, &objtype);
108
109 *p = OSSL_PARAM_construct_end();
110
111 ok = data_cb(params, data_cbarg);
112
113 end:
114 ossl_X509_PUBKEY_INTERNAL_free(xpub);
115 OPENSSL_free(der);
116 return ok;
117 }
118
119 const OSSL_DISPATCH ossl_SubjectPublicKeyInfo_der_to_der_decoder_functions[] = {
120 { OSSL_FUNC_DECODER_NEWCTX, (void (*)(void))spki2typespki_newctx },
121 { OSSL_FUNC_DECODER_FREECTX, (void (*)(void))spki2typespki_freectx },
122 { OSSL_FUNC_DECODER_DECODE, (void (*)(void))spki2typespki_decode },
123 { 0, NULL }
124 };
125