Coverage Report

Created: 2025-11-24 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/strongswan/src/libstrongswan/plugins/pkcs1/pkcs1_builder.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2008-2016 Tobias Brunner
3
 * Copyright (C) 2008-2009 Martin Willi
4
 * Copyright (C) 2000-2008 Andreas Steffen
5
 *
6
 * Copyright (C) secunet Security Networks AG
7
 *
8
 * This program is free software; you can redistribute it and/or modify it
9
 * under the terms of the GNU General Public License as published by the
10
 * Free Software Foundation; either version 2 of the License, or (at your
11
 * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
12
 *
13
 * This program is distributed in the hope that it will be useful, but
14
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16
 * for more details.
17
 */
18
19
#include "pkcs1_builder.h"
20
21
#include <utils/debug.h>
22
#include <asn1/oid.h>
23
#include <asn1/asn1.h>
24
#include <asn1/asn1_parser.h>
25
#include <credentials/keys/private_key.h>
26
27
/**
28
 * ASN.1 definition of a subjectPublicKeyInfo structure
29
 */
30
static const asn1Object_t pkinfoObjects[] = {
31
  { 0, "subjectPublicKeyInfo",ASN1_SEQUENCE,    ASN1_NONE }, /* 0 */
32
  { 1,   "algorithm",     ASN1_EOC,     ASN1_RAW  }, /* 1 */
33
  { 1,   "subjectPublicKey",  ASN1_BIT_STRING,  ASN1_BODY }, /* 2 */
34
  { 0, "exit",        ASN1_EOC,     ASN1_EXIT }
35
};
36
0
#define PKINFO_SUBJECT_PUBLIC_KEY_ALGORITHM 1
37
0
#define PKINFO_SUBJECT_PUBLIC_KEY     2
38
39
/**
40
 * Load a generic public key from an ASN.1 encoded blob
41
 */
42
static public_key_t *parse_public_key(chunk_t blob)
43
0
{
44
0
  asn1_parser_t *parser;
45
0
  chunk_t object;
46
0
  int objectID;
47
0
  public_key_t *key = NULL;
48
0
  key_type_t type = KEY_ANY;
49
50
0
  parser = asn1_parser_create(pkinfoObjects, blob);
51
52
0
  while (parser->iterate(parser, &objectID, &object))
53
0
  {
54
0
    switch (objectID)
55
0
    {
56
0
      case PKINFO_SUBJECT_PUBLIC_KEY_ALGORITHM:
57
0
      {
58
0
        int oid = asn1_parse_algorithmIdentifier(object,
59
0
                    parser->get_level(parser)+1, NULL);
60
61
0
        if (oid == OID_RSA_ENCRYPTION || oid == OID_RSAES_OAEP ||
62
0
          oid == OID_RSASSA_PSS)
63
0
        {
64
          /* TODO: we should parse parameters for PSS and pass them
65
           * (and the type), or the complete subjectPublicKeyInfo,
66
           * along so we can treat these as restrictions when
67
           * generating signatures with the associated private key */
68
0
          type = KEY_RSA;
69
0
        }
70
0
        else if (oid == OID_EC_PUBLICKEY)
71
0
        {
72
          /* Need the whole subjectPublicKeyInfo for EC public keys */
73
0
          key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY,
74
0
                KEY_ECDSA, BUILD_BLOB_ASN1_DER, blob, BUILD_END);
75
0
          goto end;
76
0
        }
77
0
        else if (oid == OID_ED25519)
78
0
        {
79
          /* Need the whole subjectPublicKeyInfo for Ed25519 public keys */
80
0
          key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY,
81
0
                KEY_ED25519, BUILD_BLOB_ASN1_DER, blob, BUILD_END);
82
0
          goto end;
83
0
        }
84
0
        else if (oid == OID_ED448)
85
0
        {
86
          /* Need the whole subjectPublicKeyInfo for Ed448 public keys */
87
0
          key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY,
88
0
                KEY_ED448, BUILD_BLOB_ASN1_DER, blob, BUILD_END);
89
0
          goto end;
90
0
        }
91
0
        else
92
0
        {
93
          /* key type not supported */
94
0
          goto end;
95
0
        }
96
0
        break;
97
0
      }
98
0
      case PKINFO_SUBJECT_PUBLIC_KEY:
99
0
        if (object.len > 0 && *object.ptr == 0x00)
100
0
        {
101
          /* skip initial bit string octet defining 0 unused bits */
102
0
          object = chunk_skip(object, 1);
103
0
        }
104
0
        DBG2(DBG_ASN, "-- > --");
105
0
        key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, type,
106
0
                     BUILD_BLOB_ASN1_DER, object, BUILD_END);
107
0
        DBG2(DBG_ASN, "-- < --");
108
0
        break;
109
0
    }
110
0
  }
111
112
0
end:
113
0
  parser->destroy(parser);
114
0
  return key;
115
0
}
116
117
/**
118
 * ASN.1 definition of RSApublicKey
119
 */
120
static const asn1Object_t pubkeyObjects[] = {
121
  { 0, "RSAPublicKey",    ASN1_SEQUENCE,  ASN1_OBJ  }, /*  0 */
122
  { 1,   "modulus",     ASN1_INTEGER, ASN1_BODY }, /*  1 */
123
  { 1,   "publicExponent",  ASN1_INTEGER, ASN1_BODY }, /*  2 */
124
  { 0, "exit",        ASN1_EOC,   ASN1_EXIT }
125
};
126
#define PUB_KEY_RSA_PUBLIC_KEY    0
127
0
#define PUB_KEY_MODULUS       1
128
0
#define PUB_KEY_EXPONENT      2
129
130
/**
131
 * Load a RSA public key from an ASN.1 encoded blob.
132
 */
133
static public_key_t *parse_rsa_public_key(chunk_t blob)
134
0
{
135
0
  chunk_t n, e;
136
0
  asn1_parser_t *parser;
137
0
  chunk_t object;
138
0
  int objectID;
139
0
  bool success = FALSE;
140
141
0
  parser = asn1_parser_create(pubkeyObjects, blob);
142
143
0
  while (parser->iterate(parser, &objectID, &object))
144
0
  {
145
0
    switch (objectID)
146
0
    {
147
0
      case PUB_KEY_MODULUS:
148
0
        n = object;
149
0
        break;
150
0
      case PUB_KEY_EXPONENT:
151
0
        e = object;
152
0
        break;
153
0
    }
154
0
  }
155
0
  success = parser->success(parser);
156
0
  parser->destroy(parser);
157
158
0
  if (!success)
159
0
  {
160
0
    return NULL;
161
0
  }
162
0
  return lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
163
0
            BUILD_RSA_MODULUS, n, BUILD_RSA_PUB_EXP, e, BUILD_END);
164
0
}
165
166
/**
167
 * ASN.1 definition of a PKCS#1 RSA private key
168
 */
169
static const asn1Object_t privkeyObjects[] = {
170
  { 0, "RSAPrivateKey",   ASN1_SEQUENCE,     ASN1_NONE }, /*  0 */
171
  { 1,   "version",     ASN1_INTEGER,      ASN1_BODY }, /*  1 */
172
  { 1,   "modulus",     ASN1_INTEGER,      ASN1_BODY }, /*  2 */
173
  { 1,   "publicExponent",  ASN1_INTEGER,      ASN1_BODY }, /*  3 */
174
  { 1,   "privateExponent", ASN1_INTEGER,      ASN1_BODY }, /*  4 */
175
  { 1,   "prime1",      ASN1_INTEGER,      ASN1_BODY }, /*  5 */
176
  { 1,   "prime2",      ASN1_INTEGER,      ASN1_BODY }, /*  6 */
177
  { 1,   "exponent1",     ASN1_INTEGER,      ASN1_BODY }, /*  7 */
178
  { 1,   "exponent2",     ASN1_INTEGER,      ASN1_BODY }, /*  8 */
179
  { 1,   "coefficient",   ASN1_INTEGER,      ASN1_BODY }, /*  9 */
180
  { 1,   "otherPrimeInfos", ASN1_SEQUENCE,     ASN1_OPT |
181
                           ASN1_LOOP }, /* 10 */
182
  { 2,     "otherPrimeInfo",  ASN1_SEQUENCE,     ASN1_NONE }, /* 11 */
183
  { 3,       "prime",     ASN1_INTEGER,      ASN1_BODY }, /* 12 */
184
  { 3,       "exponent",    ASN1_INTEGER,      ASN1_BODY }, /* 13 */
185
  { 3,       "coefficient", ASN1_INTEGER,      ASN1_BODY }, /* 14 */
186
  { 1,   "end opt or loop", ASN1_EOC,          ASN1_END  }, /* 15 */
187
  { 0, "exit",        ASN1_EOC,          ASN1_EXIT }
188
};
189
0
#define PRIV_KEY_VERSION     1
190
0
#define PRIV_KEY_MODULUS     2
191
0
#define PRIV_KEY_PUB_EXP     3
192
0
#define PRIV_KEY_PRIV_EXP    4
193
0
#define PRIV_KEY_PRIME1      5
194
0
#define PRIV_KEY_PRIME2      6
195
0
#define PRIV_KEY_EXP1      7
196
0
#define PRIV_KEY_EXP2      8
197
0
#define PRIV_KEY_COEFF       9
198
199
/**
200
 * Load a RSA private key from a ASN1 encoded blob.
201
 */
202
static private_key_t *parse_rsa_private_key(chunk_t blob)
203
0
{
204
0
  chunk_t n, e, d, p, q, exp1, exp2, coeff;
205
0
  asn1_parser_t *parser;
206
0
  chunk_t object;
207
0
  int objectID ;
208
0
  bool success = FALSE;
209
210
0
  parser = asn1_parser_create(privkeyObjects, blob);
211
0
  parser->set_flags(parser, FALSE, TRUE);
212
213
0
  while (parser->iterate(parser, &objectID, &object))
214
0
  {
215
0
    switch (objectID)
216
0
    {
217
0
      case PRIV_KEY_VERSION:
218
0
        if (object.len > 0 && *object.ptr != 0)
219
0
        {
220
0
          goto end;
221
0
        }
222
0
        break;
223
0
      case PRIV_KEY_MODULUS:
224
0
        n = object;
225
0
        break;
226
0
      case PRIV_KEY_PUB_EXP:
227
0
        e = object;
228
0
        break;
229
0
      case PRIV_KEY_PRIV_EXP:
230
0
        d = object;
231
0
        break;
232
0
      case PRIV_KEY_PRIME1:
233
0
        p = object;
234
0
        break;
235
0
      case PRIV_KEY_PRIME2:
236
0
        q = object;
237
0
        break;
238
0
      case PRIV_KEY_EXP1:
239
0
        exp1 = object;
240
0
        break;
241
0
      case PRIV_KEY_EXP2:
242
0
        exp2 = object;
243
0
        break;
244
0
      case PRIV_KEY_COEFF:
245
0
        coeff = object;
246
0
        break;
247
0
    }
248
0
  }
249
0
  success = parser->success(parser);
250
251
0
end:
252
0
  parser->destroy(parser);
253
0
  if (!success)
254
0
  {
255
0
    return NULL;
256
0
  }
257
0
  return lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
258
0
      BUILD_RSA_MODULUS, n, BUILD_RSA_PUB_EXP, e, BUILD_RSA_PRIV_EXP, d,
259
0
      BUILD_RSA_PRIME1, p,  BUILD_RSA_PRIME2, q, BUILD_RSA_EXP1, exp1,
260
0
      BUILD_RSA_EXP2, exp2, BUILD_RSA_COEFF, coeff, BUILD_END);
261
0
}
262
263
/**
264
 * Check if the ASN.1 structure looks like an EC private key according to
265
 * RFC 5915.
266
 *
267
 * ECPrivateKey :=: SEQUENCE {
268
 *   version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
269
 *   privateKey     OCTET STRING,
270
 *   parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
271
 *   publicKey  [1] BIT STRING OPTIONAL
272
 * }
273
 *
274
 * While the parameters and publicKey fields are OPTIONAL, RFC 5915 says that
275
 * parameters MUST be included (an errata clarifies this, so this is only the
276
 * case for plain private keys, not encoded in PKCS#8) and publicKey SHOULD be.
277
 */
278
static bool is_ec_private_key(chunk_t blob)
279
0
{
280
0
  chunk_t data;
281
0
  return asn1_unwrap(&blob, &blob) == ASN1_SEQUENCE &&
282
0
       asn1_unwrap(&blob, &data) == ASN1_INTEGER &&
283
0
       asn1_parse_integer_uint64(data) == 1 &&
284
0
       asn1_unwrap(&blob, &data) == ASN1_OCTET_STRING &&
285
0
       asn1_unwrap(&blob, &data) == ASN1_CONTEXT_C_0 &&
286
0
       asn1_unwrap(&data, &data) == ASN1_OID &&
287
0
       (!blob.len || (asn1_unwrap(&blob, &data) == ASN1_CONTEXT_C_1));
288
0
}
289
290
/**
291
 * Load a private key from an ASN.1 encoded blob trying to detect the type
292
 * automatically.
293
 */
294
static private_key_t *parse_private_key(chunk_t blob)
295
0
{
296
0
  if (is_ec_private_key(blob))
297
0
  {
298
0
    return lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ECDSA,
299
0
                  BUILD_BLOB_ASN1_DER, blob, BUILD_END);
300
0
  }
301
0
  return parse_rsa_private_key(blob);
302
0
}
303
304
/**
305
 * See header.
306
 */
307
public_key_t *pkcs1_public_key_load(key_type_t type, va_list args)
308
0
{
309
0
  chunk_t blob = chunk_empty;
310
311
0
  while (TRUE)
312
0
  {
313
0
    switch (va_arg(args, builder_part_t))
314
0
    {
315
0
      case BUILD_BLOB_ASN1_DER:
316
0
        blob = va_arg(args, chunk_t);
317
0
        continue;
318
0
      case BUILD_END:
319
0
        break;
320
0
      default:
321
0
        return NULL;
322
0
    }
323
0
    break;
324
0
  }
325
0
  switch (type)
326
0
  {
327
0
    case KEY_ANY:
328
0
      return parse_public_key(blob);
329
0
    case KEY_RSA:
330
0
      return parse_rsa_public_key(blob);
331
0
    default:
332
0
      return NULL;
333
0
  }
334
0
}
335
336
/**
337
 * See header.
338
 */
339
private_key_t *pkcs1_private_key_load(key_type_t type, va_list args)
340
0
{
341
0
  chunk_t blob = chunk_empty;
342
343
0
  while (TRUE)
344
0
  {
345
0
    switch (va_arg(args, builder_part_t))
346
0
    {
347
0
      case BUILD_BLOB_ASN1_DER:
348
0
        blob = va_arg(args, chunk_t);
349
0
        continue;
350
0
      case BUILD_END:
351
0
        break;
352
0
      default:
353
0
        return NULL;
354
0
    }
355
0
    break;
356
0
  }
357
0
  switch (type)
358
0
  {
359
0
    case KEY_ANY:
360
0
      return parse_private_key(blob);
361
0
    case KEY_RSA:
362
0
      return parse_rsa_private_key(blob);
363
0
    default:
364
      return NULL;
365
0
  }
366
0
}
367