1 /*
2  *
3  * Copyright 2020 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 // This is a sample openSSL engine which tests the openSSL
20 // engine plugability with gRPC.
21 // This sample engine expects KeyId to be actual PEM encoded
22 // key itself and just calls standard openSSL functions.
23 
24 #include <openssl/bio.h>
25 #include <openssl/engine.h>
26 #include <openssl/pem.h>
27 
28 #ifndef OPENSSL_IS_BORINGSSL
29 
30 #include <stdio.h>
31 #include <string.h>
32 
33 extern "C" {
34 static const char engine_id[] = "libengine_passthrough";
35 static const char engine_name[] = "A passthrough engine for private keys";
36 static int e_passthrough_idx = -1;
37 
e_passthrough_init(ENGINE * e)38 static int e_passthrough_init(ENGINE* e) {
39   if (e_passthrough_idx < 0) {
40     e_passthrough_idx = ENGINE_get_ex_new_index(0, NULL, NULL, NULL, 0);
41     if (e_passthrough_idx < 0) return 0;
42   }
43   return 1;
44 }
45 
e_passthrough_load_privkey(ENGINE * eng,const char * key_id,UI_METHOD * ui_method,void * callback_data)46 EVP_PKEY* e_passthrough_load_privkey(ENGINE* eng, const char* key_id,
47                                      UI_METHOD* ui_method,
48                                      void* callback_data) {
49   EVP_PKEY* pkey = NULL;
50   BIO* pem = BIO_new_mem_buf((void*)key_id, (int)(strlen(key_id)));
51   if (pem == NULL) return NULL;
52   pkey = PEM_read_bio_PrivateKey(pem, NULL, NULL, (void*)"");
53   BIO_free(pem);
54   return pkey;
55 }
56 
passthrough_bind_helper(ENGINE * e,const char * id)57 int passthrough_bind_helper(ENGINE* e, const char* id) {
58   if (id && strcmp(id, engine_id)) {
59     return 0;
60   }
61   if (!ENGINE_set_id(e, engine_id) || !ENGINE_set_name(e, engine_name) ||
62       !ENGINE_set_flags(e, ENGINE_FLAGS_NO_REGISTER_ALL) ||
63       !ENGINE_set_init_function(e, e_passthrough_init) ||
64       !ENGINE_set_load_privkey_function(e, e_passthrough_load_privkey)) {
65     return 0;
66   }
67   return 1;
68 }
69 
70 IMPLEMENT_DYNAMIC_BIND_FN(passthrough_bind_helper)
71 IMPLEMENT_DYNAMIC_CHECK_FN()
72 }
73 #endif  // OPENSSL_IS_BORINGSSL
74