Coverage Report

Created: 2026-05-16 07:02

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/strongswan/src/libstrongswan/plugins/openssl/openssl_engine.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2008-2018 Tobias Brunner
3
 * Copyright (C) 2008 Martin Willi
4
 *
5
 * Copyright (C) secunet Security Networks AG
6
 *
7
 * This program is free software; you can redistribute it and/or modify it
8
 * under the terms of the GNU General Public License as published by the
9
 * Free Software Foundation; either version 2 of the License, or (at your
10
 * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
11
 *
12
 * This program is distributed in the hope that it will be useful, but
13
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15
 * for more details.
16
 */
17
18
/* the ENGINE API has been deprecated with OpenSSL 3.0 (the provider API should
19
 * be used instead) */
20
#define OPENSSL_SUPPRESS_DEPRECATED
21
22
#include <openssl/opensslv.h>
23
#include <openssl/opensslconf.h>
24
25
#include "openssl_engine.h"
26
27
#if !defined(OPENSSL_NO_ENGINE) && \
28
  (OPENSSL_VERSION_NUMBER < 0x30000000L || !defined(OPENSSL_NO_DEPRECATED))
29
30
#include <openssl/engine.h>
31
32
#include "openssl_util.h"
33
34
/**
35
 * Login to engine with a PIN specified for a keyid
36
 */
37
static bool login(ENGINE *engine, chunk_t keyid)
38
0
{
39
0
  enumerator_t *enumerator;
40
0
  shared_key_t *shared;
41
0
  identification_t *id;
42
0
  chunk_t key;
43
0
  char pin[64];
44
0
  bool found = FALSE, success = FALSE;
45
46
0
  id = identification_create_from_encoding(ID_KEY_ID, keyid);
47
0
  enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr,
48
0
                            SHARED_PIN, id, NULL);
49
0
  while (enumerator->enumerate(enumerator, &shared, NULL, NULL))
50
0
  {
51
0
    found = TRUE;
52
0
    key = shared->get_key(shared);
53
0
    if (snprintf(pin, sizeof(pin),
54
0
           "%.*s", (int)key.len, key.ptr) >= sizeof(pin))
55
0
    {
56
0
      continue;
57
0
    }
58
0
    if (ENGINE_ctrl_cmd_string(engine, "PIN", pin, 0))
59
0
    {
60
0
      success = TRUE;
61
0
      break;
62
0
    }
63
0
    else
64
0
    {
65
0
      DBG1(DBG_CFG, "setting PIN on engine failed");
66
0
    }
67
0
  }
68
0
  enumerator->destroy(enumerator);
69
0
  id->destroy(id);
70
0
  if (!found)
71
0
  {
72
0
    DBG1(DBG_CFG, "no PIN found for %#B", &keyid);
73
0
  }
74
0
  return success;
75
0
}
76
77
/*
78
 * Described in header
79
 */
80
private_key_t *openssl_private_key_connect(key_type_t type, va_list args)
81
0
{
82
0
  char *engine_id = NULL;
83
0
  char keyname[BUF_LEN];
84
0
  chunk_t keyid = chunk_empty;
85
0
  EVP_PKEY *key;
86
0
  ENGINE *engine;
87
0
  int slot = -1;
88
89
0
  while (TRUE)
90
0
  {
91
0
    switch (va_arg(args, builder_part_t))
92
0
    {
93
0
      case BUILD_PKCS11_KEYID:
94
0
        keyid = va_arg(args, chunk_t);
95
0
        continue;
96
0
      case BUILD_PKCS11_SLOT:
97
0
        slot = va_arg(args, int);
98
0
        continue;
99
0
      case BUILD_PKCS11_MODULE:
100
0
        engine_id = va_arg(args, char*);
101
0
        continue;
102
0
      case BUILD_END:
103
0
        break;
104
0
      default:
105
0
        return NULL;
106
0
    }
107
0
    break;
108
0
  }
109
0
  if (!keyid.len)
110
0
  {
111
0
    return NULL;
112
0
  }
113
114
0
  memset(keyname, 0, sizeof(keyname));
115
0
  if (slot != -1)
116
0
  {
117
0
    snprintf(keyname, sizeof(keyname), "%d:", slot);
118
0
  }
119
0
  if (sizeof(keyname) - strlen(keyname) <= keyid.len * 2 + 1)
120
0
  {
121
0
    return NULL;
122
0
  }
123
0
  chunk_to_hex(keyid, keyname + strlen(keyname), FALSE);
124
125
0
  if (!engine_id)
126
0
  {
127
0
    engine_id = lib->settings->get_str(lib->settings,
128
0
              "%s.plugins.openssl.engine_id", "pkcs11", lib->ns);
129
0
  }
130
0
  engine = ENGINE_by_id(engine_id);
131
0
  if (!engine)
132
0
  {
133
0
    DBG2(DBG_LIB, "engine '%s' is not available", engine_id);
134
0
    return NULL;
135
0
  }
136
0
  if (!ENGINE_init(engine))
137
0
  {
138
0
    DBG1(DBG_LIB, "failed to initialize engine '%s'", engine_id);
139
0
    ENGINE_free(engine);
140
0
    return NULL;
141
0
  }
142
0
  ENGINE_free(engine);
143
0
  if (!login(engine, keyid))
144
0
  {
145
0
    DBG1(DBG_LIB, "login to engine '%s' failed", engine_id);
146
0
    ENGINE_finish(engine);
147
0
    return NULL;
148
0
  }
149
0
  key = ENGINE_load_private_key(engine, keyname, NULL, NULL);
150
0
  ENGINE_finish(engine);
151
0
  if (!key)
152
0
  {
153
0
    DBG1(DBG_LIB, "failed to load private key with ID '%s' from "
154
0
       "engine '%s'", keyname, engine_id);
155
0
    return NULL;
156
0
  }
157
0
  return openssl_wrap_private_key(key, TRUE);
158
0
}
159
160
/*
161
 * Described in header
162
 */
163
void openssl_engine_deinit()
164
0
{
165
#if OPENSSL_VERSION_NUMBER < 0x10100000L
166
  ENGINE_cleanup();
167
#endif
168
0
}
169
170
/*
171
 * Described in header
172
 */
173
void openssl_engine_init()
174
0
{
175
#if OPENSSL_VERSION_NUMBER < 0x10100000L
176
  /* activate support for hardware accelerators */
177
  ENGINE_load_builtin_engines();
178
  ENGINE_register_all_complete();
179
#endif
180
0
}
181
182
#else /* OPENSSL_NO_ENGINE */
183
184
private_key_t *openssl_private_key_connect(key_type_t type, va_list args)
185
{
186
  return NULL;
187
}
188
189
void openssl_engine_deinit() {}
190
191
void openssl_engine_init() {}
192
193
#endif /* OPENSSL_NO_ENGINE */