2 * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
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
12 #include <openssl/evp.h>
13 #include "internal/asn1_int.h"
16 * If this symbol is defined then ENGINE_get_pkey_asn1_meth_engine(), the
17 * function that is used by EVP to hook in pkey_asn1_meth code and cache
18 * defaults (etc), will display brief debugging summaries to stderr with the
21 /* #define ENGINE_PKEY_ASN1_METH_DEBUG */
23 static ENGINE_TABLE
*pkey_asn1_meth_table
= NULL
;
25 void ENGINE_unregister_pkey_asn1_meths(ENGINE
*e
)
27 engine_table_unregister(&pkey_asn1_meth_table
, e
);
30 static void engine_unregister_all_pkey_asn1_meths(void)
32 engine_table_cleanup(&pkey_asn1_meth_table
);
35 int ENGINE_register_pkey_asn1_meths(ENGINE
*e
)
37 if (e
->pkey_asn1_meths
) {
39 int num_nids
= e
->pkey_asn1_meths(e
, NULL
, &nids
, 0);
41 return engine_table_register(&pkey_asn1_meth_table
,
42 engine_unregister_all_pkey_asn1_meths
,
43 e
, nids
, num_nids
, 0);
48 void ENGINE_register_all_pkey_asn1_meths(void)
52 for (e
= ENGINE_get_first(); e
; e
= ENGINE_get_next(e
))
53 ENGINE_register_pkey_asn1_meths(e
);
56 int ENGINE_set_default_pkey_asn1_meths(ENGINE
*e
)
58 if (e
->pkey_asn1_meths
) {
60 int num_nids
= e
->pkey_asn1_meths(e
, NULL
, &nids
, 0);
62 return engine_table_register(&pkey_asn1_meth_table
,
63 engine_unregister_all_pkey_asn1_meths
,
64 e
, nids
, num_nids
, 1);
70 * Exposed API function to get a functional reference from the implementation
71 * table (ie. try to get a functional reference from the tabled structural
72 * references) for a given pkey_asn1_meth 'nid'
74 ENGINE
*ENGINE_get_pkey_asn1_meth_engine(int nid
)
76 return engine_table_select(&pkey_asn1_meth_table
, nid
);
80 * Obtains a pkey_asn1_meth implementation from an ENGINE functional
83 const EVP_PKEY_ASN1_METHOD
*ENGINE_get_pkey_asn1_meth(ENGINE
*e
, int nid
)
85 EVP_PKEY_ASN1_METHOD
*ret
;
86 ENGINE_PKEY_ASN1_METHS_PTR fn
= ENGINE_get_pkey_asn1_meths(e
);
87 if (!fn
|| !fn(e
, &ret
, NULL
, nid
)) {
88 ENGINEerr(ENGINE_F_ENGINE_GET_PKEY_ASN1_METH
,
89 ENGINE_R_UNIMPLEMENTED_PUBLIC_KEY_METHOD
);
95 /* Gets the pkey_asn1_meth callback from an ENGINE structure */
96 ENGINE_PKEY_ASN1_METHS_PTR
ENGINE_get_pkey_asn1_meths(const ENGINE
*e
)
98 return e
->pkey_asn1_meths
;
101 /* Sets the pkey_asn1_meth callback in an ENGINE structure */
102 int ENGINE_set_pkey_asn1_meths(ENGINE
*e
, ENGINE_PKEY_ASN1_METHS_PTR f
)
104 e
->pkey_asn1_meths
= f
;
109 * Internal function to free up EVP_PKEY_ASN1_METHOD structures before an
110 * ENGINE is destroyed
113 void engine_pkey_asn1_meths_free(ENGINE
*e
)
116 EVP_PKEY_ASN1_METHOD
*pkm
;
117 if (e
->pkey_asn1_meths
) {
120 npknids
= e
->pkey_asn1_meths(e
, NULL
, &pknids
, 0);
121 for (i
= 0; i
< npknids
; i
++) {
122 if (e
->pkey_asn1_meths(e
, &pkm
, NULL
, pknids
[i
])) {
123 EVP_PKEY_asn1_free(pkm
);
130 * Find a method based on a string. This does a linear search through all
131 * implemented algorithms. This is OK in practice because only a small number
132 * of algorithms are likely to be implemented in an engine and it is not used
133 * for speed critical operations.
136 const EVP_PKEY_ASN1_METHOD
*ENGINE_get_pkey_asn1_meth_str(ENGINE
*e
,
142 EVP_PKEY_ASN1_METHOD
*ameth
;
143 if (!e
->pkey_asn1_meths
)
147 nidcount
= e
->pkey_asn1_meths(e
, NULL
, &nids
, 0);
148 for (i
= 0; i
< nidcount
; i
++) {
149 e
->pkey_asn1_meths(e
, &ameth
, NULL
, nids
[i
]);
150 if (((int)strlen(ameth
->pem_str
) == len
)
151 && strncasecmp(ameth
->pem_str
, str
, len
) == 0)
159 const EVP_PKEY_ASN1_METHOD
*ameth
;
164 static void look_str_cb(int nid
, STACK_OF(ENGINE
) *sk
, ENGINE
*def
, void *arg
)
166 ENGINE_FIND_STR
*lk
= arg
;
170 for (i
= 0; i
< sk_ENGINE_num(sk
); i
++) {
171 ENGINE
*e
= sk_ENGINE_value(sk
, i
);
172 EVP_PKEY_ASN1_METHOD
*ameth
;
173 e
->pkey_asn1_meths(e
, &ameth
, NULL
, nid
);
175 && ((int)strlen(ameth
->pem_str
) == lk
->len
)
176 && strncasecmp(ameth
->pem_str
, lk
->str
, lk
->len
) == 0) {
184 const EVP_PKEY_ASN1_METHOD
*ENGINE_pkey_asn1_find_str(ENGINE
**pe
,
188 ENGINE_FIND_STR fstr
;
194 if (!RUN_ONCE(&engine_lock_init
, do_engine_lock_init
)) {
195 ENGINEerr(ENGINE_F_ENGINE_PKEY_ASN1_FIND_STR
, ERR_R_MALLOC_FAILURE
);
199 CRYPTO_THREAD_write_lock(global_engine_lock
);
200 engine_table_doall(pkey_asn1_meth_table
, look_str_cb
, &fstr
);
201 /* If found obtain a structural reference to engine */
203 fstr
.e
->struct_ref
++;
204 engine_ref_debug(fstr
.e
, 0, 1);
207 CRYPTO_THREAD_unlock(global_engine_lock
);