Coverage Report

Created: 2026-10-17 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gnupg/common/compliance.c
Line
Count
Source
1
/* compliance.c - Functions for compliance modi
2
 * Copyright (C) 2017 g10 Code GmbH
3
 * Copyright (C) 2017 Bundesamt für Sicherheit in der Informationstechnik
4
 *
5
 * This file is part of GnuPG.
6
 *
7
 * This file is free software; you can redistribute it and/or modify
8
 * it under the terms of either
9
 *
10
 *   - the GNU Lesser General Public License as published by the Free
11
 *     Software Foundation; either version 3 of the License, or (at
12
 *     your option) any later version.
13
 *
14
 * or
15
 *
16
 *   - the GNU General Public License as published by the Free
17
 *     Software Foundation; either version 2 of the License, or (at
18
 *     your option) any later version.
19
 *
20
 * or both in parallel, as here.
21
 *
22
 * This file is distributed in the hope that it will be useful,
23
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25
 * GNU General Public License for more details.
26
 *
27
 * You should have received a copy of the GNU General Public License
28
 * along with this program; if not, see <https://www.gnu.org/licenses/>.
29
 */
30
31
#include <config.h>
32
#include <gcrypt.h>
33
34
#include "openpgpdefs.h"
35
#include "logging.h"
36
#include "util.h"
37
#include "i18n.h"
38
#include "compliance.h"
39
40
static int initialized;
41
static int module;
42
43
44
/* This value is used by DSA and RSA checks in addition to the hard
45
 * coded length checks.  It allows one to increase the required key length
46
 * using a config file.  */
47
static unsigned int min_compliant_rsa_length;
48
49
50
/* Kludge to allow testing of the compliance options while not yet
51
 * approved. */
52
static int
53
get_assumed_de_vs_compliance (void)
54
0
{
55
#if 0  /* Set to 1 if the software suite has been approved.  */
56
  return 0;
57
#else
58
0
  static int value = -1;
59
60
0
  if (value == -1)
61
0
    {
62
0
      const char *s = getenv ("GNUPG_ASSUME_COMPLIANCE");
63
0
      value = (s && !strcmp (s, "de-vs"));
64
#ifdef HAVE_W32_SYSTEM
65
      if (!value)
66
        {
67
          char *tmp;
68
          tmp = read_w32_registry_string (NULL,
69
                                          gnupg_registry_dir (),
70
                                          "GNUPG_ASSUME_COMPLIANCE");
71
          if (tmp && !strcmp (tmp, "de-vs"))
72
            value = 1;
73
          xfree (tmp);
74
        }
75
#endif /* W32 */
76
0
    }
77
0
  return value > 0;
78
0
#endif
79
0
}
80
81
/* Return the address of a compliance cache variable for COMPLIANCE.
82
 * If no such variable exists NULL is returned.  FOR_RNG returns the
83
 * cache variable for the RNG compliance check. */
84
static int *
85
get_compliance_cache (enum gnupg_compliance_mode compliance, int for_rng)
86
0
{
87
0
  static int r_gnupg   = -1, s_gnupg   = -1;
88
0
  static int r_rfc4880 = -1, s_rfc4880 = -1;
89
0
  static int r_rfc2440 = -1, s_rfc2440 = -1;
90
0
  static int r_pgp7    = -1, s_pgp7    = -1;
91
0
  static int r_pgp8    = -1, s_pgp8    = -1;
92
0
  static int r_de_vs   = -1, s_de_vs   = -1;
93
0
  static int r_fips    = -1, s_fips    = -1;
94
95
0
  int *ptr = NULL;
96
97
0
  switch (compliance)
98
0
    {
99
0
    case CO_GNUPG:   ptr = for_rng? &r_gnupg   : &s_gnupg  ; break;
100
0
    case CO_RFC4880: ptr = for_rng? &r_rfc4880 : &s_rfc4880; break;
101
0
    case CO_RFC2440: ptr = for_rng? &r_rfc2440 : &s_rfc2440; break;
102
0
    case CO_PGP7:    ptr = for_rng? &r_pgp7    : &s_pgp7   ; break;
103
0
    case CO_PGP8:    ptr = for_rng? &r_pgp8    : &s_pgp8   ; break;
104
0
    case CO_DE_VS:   ptr = for_rng? &r_de_vs   : &s_de_vs  ; break;
105
0
    case CO_FIPS:    ptr = for_rng? &r_fips    : &s_fips   ; break;
106
0
    }
107
108
0
  if (ptr && compliance == CO_DE_VS)
109
0
    {
110
0
      if (get_assumed_de_vs_compliance ())
111
0
        *ptr = 1;
112
0
    }
113
114
115
0
  return ptr;
116
0
}
117
118
119
/* Initializes the module.  Must be called with the current
120
 * GNUPG_MODULE_NAME.  Checks a few invariants, and tunes the policies
121
 * for the given module.  */
122
void
123
gnupg_initialize_compliance (int gnupg_module_name)
124
0
{
125
0
  log_assert (! initialized);
126
127
  /* We accept both OpenPGP-style and gcrypt-style algorithm ids.
128
   * Assert that they are compatible. At some places gcrypt ids are
129
   * used which can't be encoded in an OpenPGP algo octet; we also
130
   * assert this.  */
131
0
  log_assert ((int) GCRY_PK_RSA          == (int) PUBKEY_ALGO_RSA);
132
0
  log_assert ((int) GCRY_PK_RSA_E        == (int) PUBKEY_ALGO_RSA_E);
133
0
  log_assert ((int) GCRY_PK_RSA_S        == (int) PUBKEY_ALGO_RSA_S);
134
0
  log_assert ((int) GCRY_PK_ELG_E        == (int) PUBKEY_ALGO_ELGAMAL_E);
135
0
  log_assert ((int) GCRY_PK_DSA          == (int) PUBKEY_ALGO_DSA);
136
0
  log_assert ((int) GCRY_PK_ECC          == (int) PUBKEY_ALGO_ECDH);
137
0
  log_assert ((int) GCRY_PK_ELG          == (int) PUBKEY_ALGO_ELGAMAL);
138
0
  log_assert ((int) GCRY_PK_ECDSA        > 255);
139
0
  log_assert ((int) GCRY_PK_ECDH         > 255);
140
0
  log_assert ((int) GCRY_PK_EDDSA        > 255);
141
0
  log_assert ((int) GCRY_CIPHER_NONE     == (int) CIPHER_ALGO_NONE);
142
0
  log_assert ((int) GCRY_CIPHER_IDEA     == (int) CIPHER_ALGO_IDEA);
143
0
  log_assert ((int) GCRY_CIPHER_3DES     == (int) CIPHER_ALGO_3DES);
144
0
  log_assert ((int) GCRY_CIPHER_CAST5    == (int) CIPHER_ALGO_CAST5);
145
0
  log_assert ((int) GCRY_CIPHER_BLOWFISH == (int) CIPHER_ALGO_BLOWFISH);
146
0
  log_assert ((int) GCRY_CIPHER_AES      == (int) CIPHER_ALGO_AES);
147
0
  log_assert ((int) GCRY_CIPHER_AES192   == (int) CIPHER_ALGO_AES192);
148
0
  log_assert ((int) GCRY_CIPHER_AES256   == (int) CIPHER_ALGO_AES256);
149
0
  log_assert ((int) GCRY_CIPHER_TWOFISH  == (int) CIPHER_ALGO_TWOFISH);
150
0
  log_assert ((int) GCRY_MD_MD5          == (int) DIGEST_ALGO_MD5);
151
0
  log_assert ((int) GCRY_MD_SHA1         == (int) DIGEST_ALGO_SHA1);
152
0
  log_assert ((int) GCRY_MD_RMD160       == (int) DIGEST_ALGO_RMD160);
153
0
  log_assert ((int) GCRY_MD_SHA256       == (int) DIGEST_ALGO_SHA256);
154
0
  log_assert ((int) GCRY_MD_SHA384       == (int) DIGEST_ALGO_SHA384);
155
0
  log_assert ((int) GCRY_MD_SHA512       == (int) DIGEST_ALGO_SHA512);
156
0
  log_assert ((int) GCRY_MD_SHA224       == (int) DIGEST_ALGO_SHA224);
157
158
0
  switch (gnupg_module_name)
159
0
    {
160
0
    case GNUPG_MODULE_NAME_GPGSM:
161
0
    case GNUPG_MODULE_NAME_GPG:
162
0
      break;
163
164
0
    default:
165
0
      log_assert (!"no policies for this module");
166
0
    }
167
168
0
  module = gnupg_module_name;
169
0
  initialized = 1;
170
0
}
171
172
/* Return true if ALGO with a key of KEYLENGTH is compliant to the
173
 * given COMPLIANCE mode.  If KEY is not NULL, various bits of
174
 * information will be extracted from it.  If CURVENAME is not NULL, it
175
 * is assumed to be the already computed.  ALGO may be either an
176
 * OpenPGP-style pubkey_algo_t, or a gcrypt-style enum gcry_pk_algos,
177
 * both are compatible from the point of view of this function.  */
178
int
179
gnupg_pk_is_compliant (enum gnupg_compliance_mode compliance, int algo,
180
                       unsigned int algo_flags,
181
           gcry_mpi_t key[], unsigned int keylength,
182
                       const char *curvename)
183
0
{
184
0
  enum { is_rsa, is_dsa, is_elg, is_ecc, is_kem } algotype;
185
0
  int result = 0;
186
187
0
  if (! initialized)
188
0
    return 0;
189
190
0
  switch (algo)
191
0
    {
192
0
    case PUBKEY_ALGO_RSA:
193
0
    case PUBKEY_ALGO_RSA_E:
194
0
    case PUBKEY_ALGO_RSA_S:
195
0
      algotype = is_rsa;
196
0
      break;
197
198
0
    case PUBKEY_ALGO_DSA:
199
0
      algotype = is_dsa;
200
0
      break;
201
202
0
    case PUBKEY_ALGO_ELGAMAL_E:
203
0
      algotype = is_elg;
204
0
      break;
205
206
0
    case PUBKEY_ALGO_ECDH:
207
0
    case PUBKEY_ALGO_ECDSA:
208
0
    case PUBKEY_ALGO_EDDSA:
209
0
    case PUBKEY_ALGO_ED25519:
210
0
    case PUBKEY_ALGO_X25519:
211
0
    case GCRY_PK_ECDSA:
212
0
    case GCRY_PK_ECDH:
213
0
    case GCRY_PK_EDDSA:
214
0
      algotype = is_ecc;
215
0
      break;
216
217
0
    case PUBKEY_ALGO_ELGAMAL:
218
0
      return 0; /* Signing with Elgamal is not at all supported.  */
219
220
0
    case PUBKEY_ALGO_KYBER:
221
0
    case PUBKEY_ALGO_MLK768_25519:
222
0
    case PUBKEY_ALGO_MLK1024_448:
223
0
      algotype = is_kem;
224
0
      break;
225
226
0
    default: /* Unknown.  */
227
0
      return 0;
228
0
    }
229
230
0
  if (compliance == CO_DE_VS)
231
0
    {
232
0
      char *curve = NULL;
233
234
0
      switch (algotype)
235
0
        {
236
0
        case is_elg:
237
0
          result = 0;
238
0
          break;
239
240
0
        case is_rsa:
241
0
          result = ((keylength == 2048
242
0
                     || keylength == 3072
243
0
                     || keylength == 4096)
244
0
                    && keylength >= min_compliant_rsa_length);
245
          /* Although rsaPSS was not part of the original evaluation
246
           * we got word that we can claim compliance.  */
247
0
          (void)algo_flags;
248
0
          break;
249
250
0
  case is_dsa:
251
0
    if (key)
252
0
      {
253
0
        size_t P = gcry_mpi_get_nbits (key[0]);
254
0
        size_t Q = gcry_mpi_get_nbits (key[1]);
255
0
        result = (Q == 256
256
0
      && (P == 2048 || P == 3072)
257
0
                        && P >= min_compliant_rsa_length);
258
0
      }
259
0
    break;
260
261
0
        case is_ecc:
262
0
          if (!curvename && key)
263
0
            {
264
0
              curve = openpgp_oid_to_str (key[0]);
265
0
              curvename = openpgp_oid_to_curve (curve, 0);
266
0
              if (!curvename)
267
0
                curvename = curve;
268
0
            }
269
270
0
          result = (curvename
271
0
                    && (algo == PUBKEY_ALGO_ECDH
272
0
                        || algo == PUBKEY_ALGO_ECDSA
273
0
                        || algo == GCRY_PK_ECDH
274
0
                        || algo == GCRY_PK_ECDSA)
275
0
                    && (!strcmp (curvename, "brainpoolP256r1")
276
0
                        || !strcmp (curvename, "brainpoolP384r1")
277
0
                        || !strcmp (curvename, "brainpoolP512r1")));
278
0
          break;
279
280
0
        case is_kem:
281
0
          if (!curvename && key)
282
0
            {
283
0
              curve = openpgp_oid_to_str (key[0]);
284
0
              curvename = openpgp_oid_to_curve (curve, 0);
285
0
              if (!curvename)
286
0
                curvename = curve;
287
0
            }
288
289
0
          result = (curvename
290
0
                    && (keylength == 768 || keylength == 1024)
291
0
                    && (algo == PUBKEY_ALGO_KYBER)
292
0
                    && (!strcmp (curvename, "brainpoolP256r1")
293
0
                        || !strcmp (curvename, "brainpoolP384r1")
294
0
                        || !strcmp (curvename, "brainpoolP512r1")));
295
0
          break;
296
297
0
        default:
298
0
          result = 0;
299
0
        }
300
0
      xfree (curve);
301
0
    }
302
0
  else if (compliance == CO_FIPS)
303
0
    {
304
0
      char *curve = NULL;
305
306
0
      switch (algotype)
307
0
        {
308
0
        case is_elg:
309
0
          result = 0;
310
0
          break;
311
312
0
        case is_rsa:
313
0
          result = ((keylength == 3072
314
0
                     || keylength == 4096)
315
0
                    && keylength >= min_compliant_rsa_length);
316
0
          (void)algo_flags;
317
0
          break;
318
319
0
        case is_ecc:
320
0
          if (!curvename && key)
321
0
            {
322
0
              curve = openpgp_oid_to_str (key[0]);
323
0
              curvename = openpgp_oid_to_curve (curve, 0);
324
0
              if (!curvename)
325
0
                curvename = curve;
326
0
            }
327
328
0
          result = (curvename
329
0
                    && (algo == PUBKEY_ALGO_ECDH
330
0
                        || algo == PUBKEY_ALGO_ECDSA
331
0
                        || algo == GCRY_PK_ECDH
332
0
                        || algo == GCRY_PK_ECDSA)
333
0
                    && (!strcmp (curvename, "brainpoolP256r1")
334
0
                        || !strcmp (curvename, "brainpoolP384r1")
335
0
                        || !strcmp (curvename, "brainpoolP512r1")
336
0
                        || !strcmp (curvename, "NIST P-256")
337
0
                        || !strcmp (curvename, "NIST P-384")
338
0
                        || !strcmp (curvename, "NIST P-521")));
339
0
          break;
340
341
0
        case is_kem:
342
0
          if (!curvename && key)
343
0
            {
344
0
              curve = openpgp_oid_to_str (key[0]);
345
0
              curvename = openpgp_oid_to_curve (curve, 0);
346
0
              if (!curvename)
347
0
                curvename = curve;
348
0
            }
349
350
0
          result = (curvename
351
0
                    && (keylength == 768 || keylength == 1024)
352
0
                    && (algo == PUBKEY_ALGO_KYBER)
353
0
                    && (!strcmp (curvename, "brainpoolP256r1")
354
0
                        || !strcmp (curvename, "brainpoolP384r1")
355
0
                        || !strcmp (curvename, "brainpoolP512r1")
356
0
                        || !strcmp (curvename, "NIST P-256")
357
0
                        || !strcmp (curvename, "NIST P-384")
358
0
                        || !strcmp (curvename, "NIST P-521")));
359
0
          break;
360
361
0
        default:
362
0
          result = 0;
363
0
        }
364
0
      xfree (curve);
365
0
    }
366
0
  else
367
0
    {
368
0
      result = 1; /* Assume compliance.  */
369
0
    }
370
371
0
  return result;
372
0
}
373
374
375
/* This is the CO_DE_VS helper for gnupg_pk_is_allowed.  */
376
static int
377
gnupg_pk_is_allowed_de_vs (enum pk_use_case use, int algo,
378
                           unsigned int algo_flags, gcry_mpi_t key[],
379
                           unsigned int keylength, const char *curvename)
380
0
{
381
0
  int result = 0;
382
383
0
  (void)algo_flags;
384
385
0
  switch (algo)
386
0
    {
387
0
    case PUBKEY_ALGO_RSA:
388
0
    case PUBKEY_ALGO_RSA_E:
389
0
    case PUBKEY_ALGO_RSA_S:
390
0
      switch (use)
391
0
        {
392
0
        case PK_USE_DECRYPTION:
393
0
        case PK_USE_VERIFICATION:
394
0
          result = 1;
395
0
          break;
396
0
        case PK_USE_ENCRYPTION:
397
0
        case PK_USE_SIGNING:
398
0
          result = ((keylength == 2048
399
0
                     || keylength == 3072
400
0
                     || keylength == 4096)
401
0
                    && keylength >= min_compliant_rsa_length);
402
0
          break;
403
0
        default:
404
0
          log_assert (!"reached");
405
0
        }
406
0
      break;
407
408
0
    case PUBKEY_ALGO_DSA:
409
0
      if (use == PK_USE_VERIFICATION)
410
0
        result = 1;
411
0
      else if (use == PK_USE_SIGNING && key)
412
0
        {
413
0
          size_t P = gcry_mpi_get_nbits (key[0]);
414
0
          size_t Q = gcry_mpi_get_nbits (key[1]);
415
0
          result = (Q == 256
416
0
                    && (P == 2048 || P == 3072)
417
0
                    && keylength >= min_compliant_rsa_length);
418
0
        }
419
0
      break;
420
421
0
    case PUBKEY_ALGO_ELGAMAL:
422
0
    case PUBKEY_ALGO_ELGAMAL_E:
423
0
      result = (use == PK_USE_DECRYPTION);
424
0
      break;
425
426
0
    case PUBKEY_ALGO_ECDH:  /* Same value as GCRY_PK_ECC, i.e. 18  */
427
0
    case GCRY_PK_ECDH:
428
0
      if (use == PK_USE_DECRYPTION)
429
0
        result = 1;
430
0
      else if (use == PK_USE_ENCRYPTION)
431
0
        {
432
0
          char *curve = NULL;
433
434
0
          if (!curvename && key)
435
0
            {
436
0
              curve = openpgp_oid_to_str (key[0]);
437
0
              curvename = openpgp_oid_to_curve (curve, 0);
438
0
              if (!curvename)
439
0
                curvename = curve;
440
0
            }
441
442
0
          result = (curvename
443
0
                    && (!strcmp (curvename, "brainpoolP256r1")
444
0
                        || !strcmp (curvename, "brainpoolP384r1")
445
0
                        || !strcmp (curvename, "brainpoolP512r1")));
446
447
0
          xfree (curve);
448
0
        }
449
0
      break;
450
451
0
    case PUBKEY_ALGO_ECDSA:
452
0
    case GCRY_PK_ECDSA:
453
0
      if (use == PK_USE_VERIFICATION)
454
0
        result = 1;
455
0
      else
456
0
        {
457
0
          char *curve = NULL;
458
459
0
          if (! curvename && key)
460
0
            {
461
0
              curve = openpgp_oid_to_str (key[0]);
462
0
              curvename = openpgp_oid_to_curve (curve, 0);
463
0
              if (!curvename)
464
0
                curvename = curve;
465
0
            }
466
467
0
          result = (use == PK_USE_SIGNING
468
0
                    && curvename
469
0
                    && (!strcmp (curvename, "brainpoolP256r1")
470
0
                        || !strcmp (curvename, "brainpoolP384r1")
471
0
                        || !strcmp (curvename, "brainpoolP512r1")));
472
0
          xfree (curve);
473
0
        }
474
0
      break;
475
476
0
    case PUBKEY_ALGO_EDDSA:
477
0
      if (use == PK_USE_VERIFICATION)
478
0
        result = 1;
479
0
      else /* We may not create such signatures in de-vs mode.  */
480
0
        result = 0;
481
0
      break;
482
483
0
    case PUBKEY_ALGO_KYBER:
484
0
      if (use == PK_USE_DECRYPTION)
485
0
        result = 1;
486
0
      else if (use == PK_USE_ENCRYPTION)
487
0
        {
488
0
          char *curve = NULL;
489
490
0
          if (!curvename && key)
491
0
            {
492
0
              curve = openpgp_oid_to_str (key[0]);
493
0
              curvename = openpgp_oid_to_curve (curve, 0);
494
0
              if (!curvename)
495
0
                curvename = curve;
496
0
            }
497
498
0
          result = (curvename
499
0
                    && (keylength == 768 || keylength == 1024)
500
0
                    && (!strcmp (curvename, "brainpoolP256r1")
501
0
                        || !strcmp (curvename, "brainpoolP384r1")
502
0
                        || !strcmp (curvename, "brainpoolP512r1")));
503
504
0
          xfree (curve);
505
0
        }
506
0
      break;
507
508
0
    case PUBKEY_ALGO_X25519:
509
0
    case PUBKEY_ALGO_MLK768_25519:
510
0
    case PUBKEY_ALGO_MLK1024_448:
511
0
      if (use == PK_USE_DECRYPTION)
512
0
        result = 1; /* Only decryption is allowed.  */
513
0
      break;
514
515
0
    default:
516
0
      break;
517
0
    }
518
519
0
  return result;
520
0
}
521
522
523
/* This is the CO_FIPS helper for gnupg_pk_is_allowed.  */
524
static int
525
gnupg_pk_is_allowed_fips (enum pk_use_case use, int algo,
526
                          unsigned int algo_flags, gcry_mpi_t key[],
527
                          unsigned int keylength, const char *curvename)
528
0
{
529
0
  int result = 0;
530
531
0
  (void)algo_flags;
532
533
0
  switch (algo)
534
0
    {
535
0
    case PUBKEY_ALGO_RSA:
536
0
    case PUBKEY_ALGO_RSA_E:
537
0
    case PUBKEY_ALGO_RSA_S:
538
0
      switch (use)
539
0
        {
540
0
        case PK_USE_DECRYPTION:
541
0
        case PK_USE_VERIFICATION:
542
0
          result = 1;
543
0
          break;
544
0
        case PK_USE_ENCRYPTION:
545
0
        case PK_USE_SIGNING:
546
0
          result = ((keylength == 3072 || keylength == 4096)
547
0
                    && keylength >= min_compliant_rsa_length);
548
0
          break;
549
0
        default:
550
0
          log_assert (!"reached");
551
0
        }
552
0
      break;
553
554
0
    case PUBKEY_ALGO_DSA:
555
0
      if (use == PK_USE_VERIFICATION)
556
0
        result = 1;
557
0
      break;
558
559
0
    case PUBKEY_ALGO_ELGAMAL:
560
0
    case PUBKEY_ALGO_ELGAMAL_E:
561
0
      result = (use == PK_USE_DECRYPTION);
562
0
      break;
563
564
0
    case PUBKEY_ALGO_ECDH:  /* Same value as GCRY_PK_ECC, i.e. 18  */
565
0
    case GCRY_PK_ECDH:
566
0
      if (use == PK_USE_DECRYPTION)
567
0
        result = 1;
568
0
      else if (use == PK_USE_ENCRYPTION)
569
0
        {
570
0
          char *curve = NULL;
571
572
0
          if (!curvename && key)
573
0
            {
574
0
              curve = openpgp_oid_to_str (key[0]);
575
0
              curvename = openpgp_oid_to_curve (curve, 0);
576
0
              if (!curvename)
577
0
                curvename = curve;
578
0
            }
579
580
0
          result = (curvename
581
0
                    && (!strcmp (curvename, "brainpoolP256r1")
582
0
                        || !strcmp (curvename, "brainpoolP384r1")
583
0
                        || !strcmp (curvename, "brainpoolP512r1")
584
0
                        || !strcmp (curvename, "NIST P-256")
585
0
                        || !strcmp (curvename, "NIST P-384")
586
0
                        || !strcmp (curvename, "NIST P-521")));
587
0
          xfree (curve);
588
0
        }
589
0
      break;
590
591
0
    case PUBKEY_ALGO_ECDSA:
592
0
    case GCRY_PK_ECDSA:
593
0
      if (use == PK_USE_VERIFICATION)
594
0
        result = 1;
595
0
      else
596
0
        {
597
0
          char *curve = NULL;
598
599
0
          if (! curvename && key)
600
0
            {
601
0
              curve = openpgp_oid_to_str (key[0]);
602
0
              curvename = openpgp_oid_to_curve (curve, 0);
603
0
              if (!curvename)
604
0
                curvename = curve;
605
0
            }
606
607
0
          result = (use == PK_USE_SIGNING
608
0
                    && curvename
609
0
                    && (!strcmp (curvename, "brainpoolP256r1")
610
0
                        || !strcmp (curvename, "brainpoolP384r1")
611
0
                        || !strcmp (curvename, "brainpoolP512r1")
612
0
                        || !strcmp (curvename, "NIST P-256")
613
0
                        || !strcmp (curvename, "NIST P-384")
614
0
                        || !strcmp (curvename, "NIST P-521")));
615
0
          xfree (curve);
616
0
        }
617
0
      break;
618
619
0
    case PUBKEY_ALGO_EDDSA:
620
0
      if (use == PK_USE_VERIFICATION)
621
0
        result = 1;
622
0
      else /* Are we allowed tocreate such signatures - needs to be checked.  */
623
0
        result = 0;
624
0
      break;
625
626
0
    case PUBKEY_ALGO_KYBER:
627
0
      if (use == PK_USE_DECRYPTION)
628
0
        result = 1;
629
0
      else if (use == PK_USE_ENCRYPTION)
630
0
        {
631
0
          char *curve = NULL;
632
633
0
          if (!curvename && key)
634
0
            {
635
0
              curve = openpgp_oid_to_str (key[0]);
636
0
              curvename = openpgp_oid_to_curve (curve, 0);
637
0
              if (!curvename)
638
0
                curvename = curve;
639
0
            }
640
641
0
          result = (curvename
642
0
                    && (keylength == 768 || keylength == 1024)
643
0
                    && (!strcmp (curvename, "brainpoolP256r1")
644
0
                        || !strcmp (curvename, "brainpoolP384r1")
645
0
                        || !strcmp (curvename, "brainpoolP512r1")
646
0
                        || !strcmp (curvename, "NIST P-256")
647
0
                        || !strcmp (curvename, "NIST P-384")
648
0
                        || !strcmp (curvename, "NIST P-521")));
649
0
          xfree (curve);
650
0
        }
651
0
      break;
652
653
0
    case PUBKEY_ALGO_X25519:
654
0
    case PUBKEY_ALGO_MLK768_25519:
655
0
    case PUBKEY_ALGO_MLK1024_448:
656
0
      if (use == PK_USE_DECRYPTION)
657
0
        result = 1; /* Only decryption is allowed.  FIXME: Why */
658
0
      break;
659
660
0
    default:
661
0
      break;
662
0
    }
663
664
0
  return result;
665
0
}
666
667
668
/* Return true if ALGO with the given KEYLENGTH is allowed in the
669
 * given COMPLIANCE mode.  USE specifies for which use case the
670
 * predicate is evaluated.  This way policies can be strict in what
671
 * they produce, and liberal in what they accept.  */
672
int
673
gnupg_pk_is_allowed (enum gnupg_compliance_mode compliance,
674
         enum pk_use_case use, int algo,
675
                     unsigned int algo_flags, gcry_mpi_t key[],
676
         unsigned int keylength, const char *curvename)
677
0
{
678
0
  int result = 0;
679
680
0
  if (! initialized)
681
0
    return 1;
682
683
  /* Map the the generic ECC algo to ECDSA if requested.  */
684
0
  if ((algo_flags & PK_ALGO_FLAG_ECC18)
685
0
      && algo == GCRY_PK_ECC
686
0
      && (use == PK_USE_VERIFICATION
687
0
          || use == PK_USE_SIGNING))
688
0
    algo = GCRY_PK_ECDSA;
689
690
0
  switch (compliance)
691
0
    {
692
0
    case CO_DE_VS:
693
0
      result = gnupg_pk_is_allowed_de_vs (use, algo, algo_flags, key,
694
0
                                          keylength, curvename);
695
0
      break;
696
697
0
    case CO_FIPS:
698
0
      result = gnupg_pk_is_allowed_fips (use, algo, algo_flags, key,
699
0
                                         keylength, curvename);
700
0
      break;
701
702
0
    default:
703
      /* The default policy is to allow all algorithms.  */
704
0
      result = 1;
705
0
    }
706
707
0
  return result;
708
0
}
709
710
711
/* Return true if (CIPHER, MODE) is compliant to the given COMPLIANCE mode.  */
712
int
713
gnupg_cipher_is_compliant (enum gnupg_compliance_mode compliance,
714
         cipher_algo_t cipher,
715
         enum gcry_cipher_modes mode)
716
0
{
717
0
  if (! initialized)
718
0
    return 0;
719
720
0
  switch (compliance)
721
0
    {
722
0
    case CO_DE_VS:
723
0
      switch (cipher)
724
0
  {
725
0
  case CIPHER_ALGO_AES:
726
0
  case CIPHER_ALGO_AES192:
727
0
  case CIPHER_ALGO_AES256:
728
0
  case CIPHER_ALGO_3DES:
729
0
    switch (module)
730
0
      {
731
0
      case GNUPG_MODULE_NAME_GPG:
732
0
        return (mode == GCRY_CIPHER_MODE_CFB
733
0
                      || mode == GCRY_CIPHER_MODE_OCB);
734
0
      case GNUPG_MODULE_NAME_GPGSM:
735
0
        return (mode == GCRY_CIPHER_MODE_CBC
736
0
                      || mode == GCRY_CIPHER_MODE_GCM);
737
0
      }
738
0
    log_assert (!"reached");
739
740
0
  default: /* for CO_DE_VS */
741
0
    return 0;
742
0
  }
743
0
      log_assert (!"reached");
744
745
0
    case CO_FIPS:
746
0
      switch (cipher)
747
0
  {
748
0
  case CIPHER_ALGO_AES:
749
0
  case CIPHER_ALGO_AES192:
750
0
  case CIPHER_ALGO_AES256:
751
0
    switch (module)
752
0
      {
753
0
      case GNUPG_MODULE_NAME_GPG:
754
0
        return (mode == GCRY_CIPHER_MODE_CFB
755
0
                      || mode == GCRY_CIPHER_MODE_GCM);
756
0
      case GNUPG_MODULE_NAME_GPGSM:
757
0
        return (mode == GCRY_CIPHER_MODE_CBC
758
0
                      || mode == GCRY_CIPHER_MODE_GCM);
759
0
      }
760
0
    log_assert (!"reached");
761
762
0
  default: /* for CO_FIPS */
763
0
    return 0;
764
0
  }
765
0
      log_assert (!"reached");
766
767
0
    default:
768
0
      return 0;
769
0
    }
770
771
0
  log_assert (!"reached");
772
0
}
773
774
775
/* Return true if CIPHER is allowed in the given COMPLIANCE mode.  If
776
 * PRODUCER is true, the predicate is evaluated for the producer, if
777
 * false for the consumer.  This way policies can be strict in what
778
 * they produce, and liberal in what they accept.  */
779
int
780
gnupg_cipher_is_allowed (enum gnupg_compliance_mode compliance, int producer,
781
       cipher_algo_t cipher,
782
       enum gcry_cipher_modes mode)
783
0
{
784
0
  if (! initialized)
785
0
    return 1;
786
787
0
  switch (compliance)
788
0
    {
789
0
    case CO_DE_VS:
790
0
      switch (cipher)
791
0
  {
792
0
  case CIPHER_ALGO_AES:
793
0
  case CIPHER_ALGO_AES192:
794
0
  case CIPHER_ALGO_AES256:
795
0
  case CIPHER_ALGO_3DES:
796
0
    switch (module)
797
0
      {
798
0
      case GNUPG_MODULE_NAME_GPG:
799
0
        return (mode == GCRY_CIPHER_MODE_NONE
800
0
                      || mode == GCRY_CIPHER_MODE_CFB
801
0
                      || mode == GCRY_CIPHER_MODE_OCB);
802
0
      case GNUPG_MODULE_NAME_GPGSM:
803
0
        return (mode == GCRY_CIPHER_MODE_NONE
804
0
                      || mode == GCRY_CIPHER_MODE_CBC
805
0
                      || mode == GCRY_CIPHER_MODE_GCM);
806
0
      }
807
0
    log_assert (!"reached");
808
809
0
  case CIPHER_ALGO_BLOWFISH:
810
0
  case CIPHER_ALGO_CAMELLIA128:
811
0
  case CIPHER_ALGO_CAMELLIA192:
812
0
  case CIPHER_ALGO_CAMELLIA256:
813
0
  case CIPHER_ALGO_CAST5:
814
0
  case CIPHER_ALGO_IDEA:
815
0
  case CIPHER_ALGO_TWOFISH:
816
0
    return (module == GNUPG_MODULE_NAME_GPG
817
0
      && (mode == GCRY_CIPHER_MODE_NONE
818
0
                      || mode == GCRY_CIPHER_MODE_CFB
819
0
                      || mode == GCRY_CIPHER_MODE_OCB)
820
0
      && ! producer);
821
0
  default: /* for CO_DE_VS */
822
0
    return 0;
823
0
  }
824
0
      log_assert (!"reached");
825
826
0
    case CO_FIPS:
827
0
      switch (cipher)
828
0
  {
829
0
  case CIPHER_ALGO_AES:
830
0
  case CIPHER_ALGO_AES192:
831
0
  case CIPHER_ALGO_AES256:
832
0
    switch (module)
833
0
      {
834
0
      case GNUPG_MODULE_NAME_GPG:
835
0
        return (mode == GCRY_CIPHER_MODE_NONE
836
0
                      || mode == GCRY_CIPHER_MODE_CFB
837
0
                      || mode == GCRY_CIPHER_MODE_GCM);
838
0
      case GNUPG_MODULE_NAME_GPGSM:
839
0
        return (mode == GCRY_CIPHER_MODE_NONE
840
0
                      || mode == GCRY_CIPHER_MODE_CBC
841
0
                      || mode == GCRY_CIPHER_MODE_GCM);
842
0
      }
843
0
    log_assert (!"reached");
844
845
0
  default: /* for CO_FIPS */
846
0
    return 0;
847
0
  }
848
0
      log_assert (!"reached");
849
850
0
    default: /* for other compliance modes. */
851
      /* The default policy is to allow all algorithms.  */
852
0
      return 1;
853
0
    }
854
855
0
  log_assert (!"reached");
856
0
}
857
858
859
/* Return true if DIGEST is compliant to the given COMPLIANCE mode.  */
860
int
861
gnupg_digest_is_compliant (enum gnupg_compliance_mode compliance,
862
                           digest_algo_t digest)
863
0
{
864
0
  if (! initialized)
865
0
    return 0;
866
867
0
  switch (compliance)
868
0
    {
869
0
    case CO_DE_VS:
870
0
    case CO_FIPS:
871
0
      switch (digest)
872
0
  {
873
0
  case DIGEST_ALGO_SHA256:
874
0
  case DIGEST_ALGO_SHA384:
875
0
  case DIGEST_ALGO_SHA512:
876
0
    return 1;
877
0
  default:
878
0
    return 0;
879
0
  }
880
0
      log_assert (!"reached");
881
882
0
    default:
883
0
      return 0;
884
0
    }
885
886
0
  log_assert (!"reached");
887
0
}
888
889
890
/* Return true if DIGEST is allowed in the given COMPLIANCE mode.  If
891
 * PRODUCER is true, the predicate is evaluated for the producer, if
892
 * false for the consumer.  This way policies can be strict in what
893
 * they produce, and liberal in what they accept.  */
894
int
895
gnupg_digest_is_allowed (enum gnupg_compliance_mode compliance, int producer,
896
       digest_algo_t digest)
897
7.41k
{
898
7.41k
  if (! initialized)
899
7.41k
    return 1;
900
901
0
  switch (compliance)
902
0
    {
903
0
    case CO_DE_VS:
904
0
      switch (digest)
905
0
  {
906
0
  case DIGEST_ALGO_SHA256:
907
0
  case DIGEST_ALGO_SHA384:
908
0
  case DIGEST_ALGO_SHA512:
909
0
    return 1;
910
0
  case DIGEST_ALGO_SHA1:
911
0
  case DIGEST_ALGO_SHA224:
912
0
  case DIGEST_ALGO_RMD160:
913
0
    return ! producer;
914
0
  case DIGEST_ALGO_MD5:
915
0
    return ! producer && module == GNUPG_MODULE_NAME_GPGSM;
916
0
  default:
917
0
    return 0;
918
0
  }
919
0
      log_assert (!"reached");
920
921
0
    case CO_FIPS:
922
0
      switch (digest)
923
0
  {
924
0
  case DIGEST_ALGO_SHA256:
925
0
  case DIGEST_ALGO_SHA384:
926
0
  case DIGEST_ALGO_SHA512:
927
0
    return 1;
928
0
  default:
929
0
    return 0;
930
0
  }
931
0
      log_assert (!"reached");
932
933
0
    default: /* for other compliance modes.  */
934
      /* The default policy is to allow all algorithms.  */
935
0
      return 1;
936
0
    }
937
938
0
  log_assert (!"reached");
939
0
}
940
941
942
/* Return True if the random number generator is compliant in
943
 * COMPLIANCE mode.  */
944
int
945
gnupg_rng_is_compliant (enum gnupg_compliance_mode compliance)
946
0
{
947
0
  int *result;
948
0
  int res;
949
950
  /* #warning debug code ahead */
951
  /* return 1; */
952
953
0
  result = get_compliance_cache (compliance, 1);
954
955
0
  if (result && *result != -1)
956
0
    res = *result; /* Use cached result.  */
957
0
  else if (compliance == CO_DE_VS || compliance == CO_FIPS)
958
0
    {
959
      /* We also check whether the library is at all compliant.  */
960
0
      res = gnupg_gcrypt_is_compliant (compliance);
961
962
      /* In DE_VS mode under Windows we also require that the JENT RNG
963
       * is active.  Check it here. */
964
#ifdef HAVE_W32_SYSTEM
965
      if (res == 1)
966
        {
967
          char *buf;
968
          const char *fields[5];
969
970
          buf = gcry_get_config (0, "rng-type");
971
          if (buf
972
              && split_fields_colon (buf, fields, DIM (fields)) >= 5
973
              && atoi (fields[4]) > 0)
974
            ; /* Field 5 > 0 := Jent is active.  */
975
          else
976
            result = 0;  /* Force non-compliance.  */
977
          gcry_free (buf);
978
        }
979
#endif /*HAVE_W32_SYSTEM*/
980
0
    }
981
0
  else
982
0
    res = 1;
983
984
0
  if (result)
985
0
    *result = res;
986
987
0
  return res;
988
0
}
989
990
991
/* Return true if the used Libgcrypt is compliant in COMPLIANCE
992
 * mode.  */
993
int
994
gnupg_gcrypt_is_compliant (enum gnupg_compliance_mode compliance)
995
0
{
996
0
  int *result;
997
0
  int res;
998
999
0
  result = get_compliance_cache (compliance, 0);
1000
1001
0
  if (result && *result != -1)
1002
0
    res = *result; /* Use cached result.  */
1003
0
  else if (compliance == CO_DE_VS)
1004
0
    {
1005
0
      int is19orlater = !!gcry_check_version ("1.9.0");
1006
1007
      /* A compliant version of GnuPG requires Libgcrypt >= 1.8.1 and
1008
       * less than 1.9.0.  Version 1.9.0 requires a re-evaluation and
1009
       * can thus not be used for de-vs.  */
1010
0
      if (gcry_check_version ("1.8.1") && !is19orlater)
1011
0
        res = 1;  /* Compliant version of Libgcrypt.  */
1012
0
      else if (is19orlater)
1013
0
        {
1014
          /* Libgcrypt might be nice enough to tell us whether it is
1015
           * compliant.  */
1016
0
          char *buf;
1017
0
          const char *fields[3];
1018
1019
0
          buf = gcry_get_config (0, "compliance");
1020
0
          if (buf
1021
0
              && split_fields_colon (buf, fields, DIM (fields)) >= 2
1022
0
              && strstr (fields[1], "de-vs"))
1023
0
            res = 1;  /* Compliant.  */
1024
0
          else
1025
0
            res = 0;  /* Non-compliant.  */
1026
0
          gcry_free (buf);
1027
0
        }
1028
0
      else
1029
0
        res = 0;  /* Non-compliant version of Libgcrypt.  */
1030
0
    }
1031
0
  else if (compliance == CO_FIPS)
1032
0
    {
1033
0
      if (gcry_check_version ("1.12.0"))
1034
0
        res = 1; /* Compliant.  */
1035
0
      else
1036
0
        res = 0;  /* Non-compliant version of Libgcrypt.  */
1037
0
    }
1038
0
  else
1039
0
    res = 1;
1040
1041
0
  if (result)
1042
0
    *result = res;
1043
1044
0
  return res;
1045
0
}
1046
1047
1048
const char *
1049
gnupg_status_compliance_flag (enum gnupg_compliance_mode compliance)
1050
0
{
1051
0
  switch (compliance)
1052
0
    {
1053
0
    case CO_GNUPG:
1054
0
      return "8";
1055
0
    case CO_RFC4880:
1056
0
    case CO_RFC2440:
1057
0
    case CO_PGP7:
1058
0
    case CO_PGP8:
1059
0
      log_assert (!"no status code assigned for this compliance mode");
1060
0
    case CO_DE_VS:
1061
0
      return get_assumed_de_vs_compliance ()? "2023" : "23";
1062
0
    case CO_FIPS:
1063
0
      return "140";
1064
0
    }
1065
0
  log_assert (!"invalid compliance mode");
1066
0
}
1067
1068
1069
1070
/* This function returns the value for the "manu" LibrePGP/rfc4880bis
1071
 * notation.  See doc/DETAILS for a description.  This value is also
1072
 * used for the manuNotation in X.509/CMS.  */
1073
const char *
1074
gnupg_manu_notation_value (enum gnupg_compliance_mode compliance)
1075
0
{
1076
0
  static char buffer[48];  /* Empty string indicates not yet initialized */
1077
0
  static char buffer2[40];
1078
1079
0
  if (!*buffer)
1080
0
    {
1081
0
      char *buf;
1082
0
      const char *s;
1083
0
      int n;
1084
0
      const char *fields[4];
1085
0
      const char *vers1, *vers2;
1086
0
      int vers1len, vers2len;
1087
0
      int arch_id, os_id;
1088
1089
0
      arch_id = 0;
1090
0
      buf = gcry_get_config (0, "cpu-arch");
1091
0
      if (buf && (n=split_fields_colon (buf, fields, DIM (fields))) >= 2)
1092
0
        {
1093
0
          if (!strcmp (fields[1], "x86") && n > 2)
1094
0
            {
1095
0
              if (!strcmp (fields[2], "amd64"))
1096
0
                arch_id = 2;
1097
0
              else if (!strcmp (fields[2], "i386"))
1098
0
                arch_id = 1;
1099
0
            }
1100
0
          else if (!strcmp (fields[1], "arm"))
1101
0
            arch_id = 3;
1102
0
        }
1103
0
      gcry_free (buf);
1104
#ifdef HAVE_W32_SYSTEM
1105
      os_id = 1;
1106
#elif defined(__linux__)
1107
      os_id = 2;
1108
#elif defined (__unix__) || defined(__APPLE__)
1109
      os_id = 3;
1110
#else
1111
      os_id = 0;
1112
#endif
1113
0
      vers1 = PACKAGE_VERSION;
1114
0
      for (s=vers1, n=0; *s; s++)
1115
0
        if (*s=='.')
1116
0
          if (++n == 2)
1117
0
            break;
1118
0
      vers1len = s-vers1;
1119
1120
0
      vers2 = gcry_check_version (NULL);
1121
0
      for (s=vers2, n=0; *s; s++)
1122
0
        if (*s=='.')
1123
0
          if (++n == 2)
1124
0
            break;
1125
0
      vers2len = s-vers2;
1126
1127
0
      snprintf (buffer2, sizeof buffer2, "2,%.*s+%.*s,%d,%d",
1128
0
                vers1len, vers1, vers2len, vers2, arch_id, os_id);
1129
0
      snprintf (buffer, sizeof buffer, "%s,%d",
1130
0
                buffer2, (compliance == CO_FIPS? 140 :
1131
0
                          get_assumed_de_vs_compliance ()? 2023 : 23));
1132
0
    }
1133
1134
0
  if (compliance == CO_DE_VS || compliance == CO_FIPS)
1135
0
    return buffer;
1136
0
  else
1137
0
    return buffer2;
1138
0
}
1139
1140
1141
/* Parse the value of --compliance.  Returns the value corresponding
1142
 * to the given STRING according to OPTIONS of size LENGTH, or -1
1143
 * indicating that the lookup was unsuccessful, or the list of options
1144
 * was printed.  If quiet is false, an additional hint to use 'help'
1145
 * is printed on unsuccessful lookups.  */
1146
int
1147
gnupg_parse_compliance_option (const char *string,
1148
             struct gnupg_compliance_option options[],
1149
             size_t length,
1150
             int quiet)
1151
0
{
1152
0
  size_t i;
1153
1154
0
  if (! ascii_strcasecmp (string, "help"))
1155
0
    {
1156
0
      log_info (_("valid values for option '%s':\n"), "--compliance");
1157
0
      for (i = 0; i < length; i++)
1158
0
        log_info ("  %s\n", options[i].keyword);
1159
0
      return -1;
1160
0
    }
1161
1162
0
  for (i = 0; i < length; i++)
1163
0
    if (! ascii_strcasecmp (string, options[i].keyword))
1164
0
      return options[i].value;
1165
1166
0
  log_error (_("invalid value for option '%s'\n"), "--compliance");
1167
0
  if (! quiet)
1168
0
    log_info (_("(use \"help\" to list choices)\n"));
1169
0
  return -1;
1170
0
}
1171
1172
1173
/* Return the command line option for the given COMPLIANCE mode.  */
1174
const char *
1175
gnupg_compliance_option_string (enum gnupg_compliance_mode compliance)
1176
0
{
1177
0
  switch (compliance)
1178
0
    {
1179
0
    case CO_GNUPG:   return "--compliance=gnupg";
1180
0
    case CO_RFC4880: return "--compliance=openpgp";
1181
0
    case CO_RFC2440: return "--compliance=rfc2440";
1182
0
    case CO_PGP7:    return "--compliance=pgp7";
1183
0
    case CO_PGP8:    return "--compliance=pgp8";
1184
0
    case CO_DE_VS:   return "--compliance=de-vs";
1185
0
    case CO_FIPS:    return "--compliance=fips";
1186
0
    }
1187
1188
0
  log_assert (!"invalid compliance mode");
1189
0
}
1190
1191
1192
/* Set additional infos for example taken from config files at startup.  */
1193
void
1194
gnupg_set_compliance_extra_info (unsigned int min_rsa)
1195
0
{
1196
0
  min_compliant_rsa_length = min_rsa;
1197
0
}