Coverage Report

Created: 2026-01-09 06:46

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
94
0
  int *ptr = NULL;
95
96
0
  switch (compliance)
97
0
    {
98
0
    case CO_GNUPG:   ptr = for_rng? &r_gnupg   : &s_gnupg  ; break;
99
0
    case CO_RFC4880: ptr = for_rng? &r_rfc4880 : &s_rfc4880; break;
100
0
    case CO_RFC2440: ptr = for_rng? &r_rfc2440 : &s_rfc2440; break;
101
0
    case CO_PGP7:    ptr = for_rng? &r_pgp7    : &s_pgp7   ; break;
102
0
    case CO_PGP8:    ptr = for_rng? &r_pgp8    : &s_pgp8   ; break;
103
0
    case CO_DE_VS:   ptr = for_rng? &r_de_vs   : &s_de_vs  ; break;
104
0
    }
105
106
0
  if (ptr && compliance == CO_DE_VS)
107
0
    {
108
0
      if (get_assumed_de_vs_compliance ())
109
0
        *ptr = 1;
110
0
    }
111
112
113
0
  return ptr;
114
0
}
115
116
117
/* Initializes the module.  Must be called with the current
118
 * GNUPG_MODULE_NAME.  Checks a few invariants, and tunes the policies
119
 * for the given module.  */
120
void
121
gnupg_initialize_compliance (int gnupg_module_name)
122
0
{
123
0
  log_assert (! initialized);
124
125
  /* We accept both OpenPGP-style and gcrypt-style algorithm ids.
126
   * Assert that they are compatible. At some places gcrypt ids are
127
   * used which can't be encoded in an OpenPGP algo octet; we also
128
   * assert this.  */
129
0
  log_assert ((int) GCRY_PK_RSA          == (int) PUBKEY_ALGO_RSA);
130
0
  log_assert ((int) GCRY_PK_RSA_E        == (int) PUBKEY_ALGO_RSA_E);
131
0
  log_assert ((int) GCRY_PK_RSA_S        == (int) PUBKEY_ALGO_RSA_S);
132
0
  log_assert ((int) GCRY_PK_ELG_E        == (int) PUBKEY_ALGO_ELGAMAL_E);
133
0
  log_assert ((int) GCRY_PK_DSA          == (int) PUBKEY_ALGO_DSA);
134
0
  log_assert ((int) GCRY_PK_ECC          == (int) PUBKEY_ALGO_ECDH);
135
0
  log_assert ((int) GCRY_PK_ELG          == (int) PUBKEY_ALGO_ELGAMAL);
136
0
  log_assert ((int) GCRY_PK_ECDSA        > 255);
137
0
  log_assert ((int) GCRY_PK_ECDH         > 255);
138
0
  log_assert ((int) GCRY_PK_EDDSA        > 255);
139
0
  log_assert ((int) GCRY_CIPHER_NONE     == (int) CIPHER_ALGO_NONE);
140
0
  log_assert ((int) GCRY_CIPHER_IDEA     == (int) CIPHER_ALGO_IDEA);
141
0
  log_assert ((int) GCRY_CIPHER_3DES     == (int) CIPHER_ALGO_3DES);
142
0
  log_assert ((int) GCRY_CIPHER_CAST5    == (int) CIPHER_ALGO_CAST5);
143
0
  log_assert ((int) GCRY_CIPHER_BLOWFISH == (int) CIPHER_ALGO_BLOWFISH);
144
0
  log_assert ((int) GCRY_CIPHER_AES      == (int) CIPHER_ALGO_AES);
145
0
  log_assert ((int) GCRY_CIPHER_AES192   == (int) CIPHER_ALGO_AES192);
146
0
  log_assert ((int) GCRY_CIPHER_AES256   == (int) CIPHER_ALGO_AES256);
147
0
  log_assert ((int) GCRY_CIPHER_TWOFISH  == (int) CIPHER_ALGO_TWOFISH);
148
0
  log_assert ((int) GCRY_MD_MD5          == (int) DIGEST_ALGO_MD5);
149
0
  log_assert ((int) GCRY_MD_SHA1         == (int) DIGEST_ALGO_SHA1);
150
0
  log_assert ((int) GCRY_MD_RMD160       == (int) DIGEST_ALGO_RMD160);
151
0
  log_assert ((int) GCRY_MD_SHA256       == (int) DIGEST_ALGO_SHA256);
152
0
  log_assert ((int) GCRY_MD_SHA384       == (int) DIGEST_ALGO_SHA384);
153
0
  log_assert ((int) GCRY_MD_SHA512       == (int) DIGEST_ALGO_SHA512);
154
0
  log_assert ((int) GCRY_MD_SHA224       == (int) DIGEST_ALGO_SHA224);
155
156
0
  switch (gnupg_module_name)
157
0
    {
158
0
    case GNUPG_MODULE_NAME_GPGSM:
159
0
    case GNUPG_MODULE_NAME_GPG:
160
0
      break;
161
162
0
    default:
163
0
      log_assert (!"no policies for this module");
164
0
    }
165
166
0
  module = gnupg_module_name;
167
0
  initialized = 1;
168
0
}
169
170
/* Return true if ALGO with a key of KEYLENGTH is compliant to the
171
 * given COMPLIANCE mode.  If KEY is not NULL, various bits of
172
 * information will be extracted from it.  If CURVENAME is not NULL, it
173
 * is assumed to be the already computed.  ALGO may be either an
174
 * OpenPGP-style pubkey_algo_t, or a gcrypt-style enum gcry_pk_algos,
175
 * both are compatible from the point of view of this function.  */
176
int
177
gnupg_pk_is_compliant (enum gnupg_compliance_mode compliance, int algo,
178
                       unsigned int algo_flags,
179
           gcry_mpi_t key[], unsigned int keylength,
180
                       const char *curvename)
181
0
{
182
0
  enum { is_rsa, is_dsa, is_elg, is_ecc, is_kem } algotype;
183
0
  int result = 0;
184
185
0
  if (! initialized)
186
0
    return 0;
187
188
0
  switch (algo)
189
0
    {
190
0
    case PUBKEY_ALGO_RSA:
191
0
    case PUBKEY_ALGO_RSA_E:
192
0
    case PUBKEY_ALGO_RSA_S:
193
0
      algotype = is_rsa;
194
0
      break;
195
196
0
    case PUBKEY_ALGO_DSA:
197
0
      algotype = is_dsa;
198
0
      break;
199
200
0
    case PUBKEY_ALGO_ELGAMAL_E:
201
0
      algotype = is_elg;
202
0
      break;
203
204
0
    case PUBKEY_ALGO_ECDH:
205
0
    case PUBKEY_ALGO_ECDSA:
206
0
    case PUBKEY_ALGO_EDDSA:
207
0
    case GCRY_PK_ECDSA:
208
0
    case GCRY_PK_ECDH:
209
0
    case GCRY_PK_EDDSA:
210
0
      algotype = is_ecc;
211
0
      break;
212
213
0
    case PUBKEY_ALGO_ELGAMAL:
214
0
      return 0; /* Signing with Elgamal is not at all supported.  */
215
216
0
    case PUBKEY_ALGO_KYBER:
217
0
      algotype = is_kem;
218
0
      break;
219
220
0
    default: /* Unknown.  */
221
0
      return 0;
222
0
    }
223
224
0
  if (compliance == CO_DE_VS)
225
0
    {
226
0
      char *curve = NULL;
227
228
0
      switch (algotype)
229
0
        {
230
0
        case is_elg:
231
0
          result = 0;
232
0
          break;
233
234
0
        case is_rsa:
235
0
          result = ((keylength == 2048
236
0
                     || keylength == 3072
237
0
                     || keylength == 4096)
238
0
                    && keylength >= min_compliant_rsa_length);
239
          /* Although rsaPSS was not part of the original evaluation
240
           * we got word that we can claim compliance.  */
241
0
          (void)algo_flags;
242
0
          break;
243
244
0
  case is_dsa:
245
0
    if (key)
246
0
      {
247
0
        size_t P = gcry_mpi_get_nbits (key[0]);
248
0
        size_t Q = gcry_mpi_get_nbits (key[1]);
249
0
        result = (Q == 256
250
0
      && (P == 2048 || P == 3072)
251
0
                        && P >= min_compliant_rsa_length);
252
0
      }
253
0
    break;
254
255
0
        case is_ecc:
256
0
          if (!curvename && key)
257
0
            {
258
0
              curve = openpgp_oid_to_str (key[0]);
259
0
              curvename = openpgp_oid_to_curve (curve, 0);
260
0
              if (!curvename)
261
0
                curvename = curve;
262
0
            }
263
264
0
          result = (curvename
265
0
                    && (algo == PUBKEY_ALGO_ECDH
266
0
                        || algo == PUBKEY_ALGO_ECDSA
267
0
                        || algo == GCRY_PK_ECDH
268
0
                        || algo == GCRY_PK_ECDSA)
269
0
                    && (!strcmp (curvename, "brainpoolP256r1")
270
0
                        || !strcmp (curvename, "brainpoolP384r1")
271
0
                        || !strcmp (curvename, "brainpoolP512r1")));
272
0
          break;
273
274
0
        case is_kem:
275
0
          if (!curvename && key)
276
0
            {
277
0
              curve = openpgp_oid_to_str (key[0]);
278
0
              curvename = openpgp_oid_to_curve (curve, 0);
279
0
              if (!curvename)
280
0
                curvename = curve;
281
0
            }
282
283
0
          result = (curvename
284
0
                    && (keylength == 768 || keylength == 1024)
285
0
                    && (algo == PUBKEY_ALGO_KYBER)
286
0
                    && (!strcmp (curvename, "brainpoolP256r1")
287
0
                        || !strcmp (curvename, "brainpoolP384r1")
288
0
                        || !strcmp (curvename, "brainpoolP512r1")));
289
0
          break;
290
291
0
        default:
292
0
          result = 0;
293
0
        }
294
0
      xfree (curve);
295
0
    }
296
0
  else
297
0
    {
298
0
      result = 1; /* Assume compliance.  */
299
0
    }
300
301
0
  return result;
302
0
}
303
304
305
/* Return true if ALGO with the given KEYLENGTH is allowed in the
306
 * given COMPLIANCE mode.  USE specifies for which use case the
307
 * predicate is evaluated.  This way policies can be strict in what
308
 * they produce, and liberal in what they accept.  */
309
int
310
gnupg_pk_is_allowed (enum gnupg_compliance_mode compliance,
311
         enum pk_use_case use, int algo,
312
                     unsigned int algo_flags, gcry_mpi_t key[],
313
         unsigned int keylength, const char *curvename)
314
0
{
315
0
  int result = 0;
316
317
0
  if (! initialized)
318
0
    return 1;
319
320
  /* Map the the generic ECC algo to ECDSA if requested.  */
321
0
  if ((algo_flags & PK_ALGO_FLAG_ECC18)
322
0
      && algo == GCRY_PK_ECC
323
0
      && (use == PK_USE_VERIFICATION
324
0
          || use == PK_USE_SIGNING))
325
0
    algo = GCRY_PK_ECDSA;
326
327
0
  switch (compliance)
328
0
    {
329
0
    case CO_DE_VS:
330
0
      switch (algo)
331
0
  {
332
0
  case PUBKEY_ALGO_RSA:
333
0
  case PUBKEY_ALGO_RSA_E:
334
0
  case PUBKEY_ALGO_RSA_S:
335
0
    switch (use)
336
0
      {
337
0
      case PK_USE_DECRYPTION:
338
0
      case PK_USE_VERIFICATION:
339
0
        result = 1;
340
0
              break;
341
0
      case PK_USE_ENCRYPTION:
342
0
      case PK_USE_SIGNING:
343
0
        result = ((keylength == 2048
344
0
                         || keylength == 3072
345
0
                         || keylength == 4096)
346
0
                        && keylength >= min_compliant_rsa_length);
347
0
              break;
348
0
      default:
349
0
        log_assert (!"reached");
350
0
      }
351
0
    break;
352
353
0
  case PUBKEY_ALGO_DSA:
354
0
          if (use == PK_USE_VERIFICATION)
355
0
            result = 1;
356
0
    else if (use == PK_USE_SIGNING && key)
357
0
      {
358
0
        size_t P = gcry_mpi_get_nbits (key[0]);
359
0
        size_t Q = gcry_mpi_get_nbits (key[1]);
360
0
        result = (Q == 256
361
0
                        && (P == 2048 || P == 3072)
362
0
                        && keylength >= min_compliant_rsa_length);
363
0
            }
364
0
          break;
365
366
0
  case PUBKEY_ALGO_ELGAMAL:
367
0
  case PUBKEY_ALGO_ELGAMAL_E:
368
0
    result = (use == PK_USE_DECRYPTION);
369
0
          break;
370
371
0
  case PUBKEY_ALGO_ECDH:  /* Same value as GCRY_PK_ECC, i.e. 18  */
372
0
  case GCRY_PK_ECDH:
373
0
    if (use == PK_USE_DECRYPTION)
374
0
            result = 1;
375
0
          else if (use == PK_USE_ENCRYPTION)
376
0
            {
377
0
              char *curve = NULL;
378
379
0
              if (!curvename && key)
380
0
                {
381
0
                  curve = openpgp_oid_to_str (key[0]);
382
0
                  curvename = openpgp_oid_to_curve (curve, 0);
383
0
                  if (!curvename)
384
0
                    curvename = curve;
385
0
                }
386
387
0
              result = (curvename
388
0
                        && (!strcmp (curvename, "brainpoolP256r1")
389
0
                            || !strcmp (curvename, "brainpoolP384r1")
390
0
                            || !strcmp (curvename, "brainpoolP512r1")));
391
392
0
              xfree (curve);
393
0
            }
394
0
          break;
395
396
0
  case PUBKEY_ALGO_ECDSA:
397
0
  case GCRY_PK_ECDSA:
398
0
          if (use == PK_USE_VERIFICATION)
399
0
            result = 1;
400
0
          else
401
0
            {
402
0
              char *curve = NULL;
403
404
0
              if (! curvename && key)
405
0
        {
406
0
    curve = openpgp_oid_to_str (key[0]);
407
0
    curvename = openpgp_oid_to_curve (curve, 0);
408
0
    if (!curvename)
409
0
      curvename = curve;
410
0
        }
411
412
0
              result = (use == PK_USE_SIGNING
413
0
                         && curvename
414
0
                         && (!strcmp (curvename, "brainpoolP256r1")
415
0
                             || !strcmp (curvename, "brainpoolP384r1")
416
0
                             || !strcmp (curvename, "brainpoolP512r1")));
417
0
              xfree (curve);
418
0
            }
419
0
          break;
420
421
422
0
  case PUBKEY_ALGO_EDDSA:
423
0
          if (use == PK_USE_VERIFICATION)
424
0
            result = 1;
425
0
          else /* We may not create such signatures in de-vs mode.  */
426
0
            result = 0;
427
0
    break;
428
429
0
  case PUBKEY_ALGO_KYBER:
430
0
    if (use == PK_USE_DECRYPTION)
431
0
            result = 1;
432
0
          else if (use == PK_USE_ENCRYPTION)
433
0
            {
434
0
              char *curve = NULL;
435
436
0
              if (!curvename && key)
437
0
                {
438
0
                  curve = openpgp_oid_to_str (key[0]);
439
0
                  curvename = openpgp_oid_to_curve (curve, 0);
440
0
                  if (!curvename)
441
0
                    curvename = curve;
442
0
                }
443
444
0
              result = (curvename
445
0
                        && (keylength == 768 || keylength == 1024)
446
0
                        && (!strcmp (curvename, "brainpoolP256r1")
447
0
                            || !strcmp (curvename, "brainpoolP384r1")
448
0
                            || !strcmp (curvename, "brainpoolP512r1")));
449
450
0
              xfree (curve);
451
0
            }
452
0
          break;
453
454
0
  default:
455
0
    break;
456
0
  }
457
0
      break;
458
459
0
    default:
460
      /* The default policy is to allow all algorithms.  */
461
0
      result = 1;
462
0
    }
463
464
0
  return result;
465
0
}
466
467
468
/* Return true if (CIPHER, MODE) is compliant to the given COMPLIANCE mode.  */
469
int
470
gnupg_cipher_is_compliant (enum gnupg_compliance_mode compliance,
471
         cipher_algo_t cipher,
472
         enum gcry_cipher_modes mode)
473
0
{
474
0
  if (! initialized)
475
0
    return 0;
476
477
0
  switch (compliance)
478
0
    {
479
0
    case CO_DE_VS:
480
0
      switch (cipher)
481
0
  {
482
0
  case CIPHER_ALGO_AES:
483
0
  case CIPHER_ALGO_AES192:
484
0
  case CIPHER_ALGO_AES256:
485
0
  case CIPHER_ALGO_3DES:
486
0
    switch (module)
487
0
      {
488
0
      case GNUPG_MODULE_NAME_GPG:
489
0
        return (mode == GCRY_CIPHER_MODE_CFB
490
0
                      || mode == GCRY_CIPHER_MODE_OCB);
491
0
      case GNUPG_MODULE_NAME_GPGSM:
492
0
        return mode == GCRY_CIPHER_MODE_CBC;
493
0
      }
494
0
    log_assert (!"reached");
495
496
0
  default:
497
0
    return 0;
498
0
  }
499
0
      log_assert (!"reached");
500
501
0
    default:
502
0
      return 0;
503
0
    }
504
505
0
  log_assert (!"reached");
506
0
}
507
508
509
/* Return true if CIPHER is allowed in the given COMPLIANCE mode.  If
510
 * PRODUCER is true, the predicate is evaluated for the producer, if
511
 * false for the consumer.  This way policies can be strict in what
512
 * they produce, and liberal in what they accept.  */
513
int
514
gnupg_cipher_is_allowed (enum gnupg_compliance_mode compliance, int producer,
515
       cipher_algo_t cipher,
516
       enum gcry_cipher_modes mode)
517
0
{
518
0
  if (! initialized)
519
0
    return 1;
520
521
0
  switch (compliance)
522
0
    {
523
0
    case CO_DE_VS:
524
0
      switch (cipher)
525
0
  {
526
0
  case CIPHER_ALGO_AES:
527
0
  case CIPHER_ALGO_AES192:
528
0
  case CIPHER_ALGO_AES256:
529
0
  case CIPHER_ALGO_3DES:
530
0
    switch (module)
531
0
      {
532
0
      case GNUPG_MODULE_NAME_GPG:
533
0
        return (mode == GCRY_CIPHER_MODE_NONE
534
0
                      || mode == GCRY_CIPHER_MODE_CFB
535
0
                      || mode == GCRY_CIPHER_MODE_OCB);
536
0
      case GNUPG_MODULE_NAME_GPGSM:
537
0
        return (mode == GCRY_CIPHER_MODE_NONE
538
0
                      || mode == GCRY_CIPHER_MODE_CBC
539
0
                      || (mode == GCRY_CIPHER_MODE_GCM && !producer));
540
0
      }
541
0
    log_assert (!"reached");
542
543
0
  case CIPHER_ALGO_BLOWFISH:
544
0
  case CIPHER_ALGO_CAMELLIA128:
545
0
  case CIPHER_ALGO_CAMELLIA192:
546
0
  case CIPHER_ALGO_CAMELLIA256:
547
0
  case CIPHER_ALGO_CAST5:
548
0
  case CIPHER_ALGO_IDEA:
549
0
  case CIPHER_ALGO_TWOFISH:
550
0
    return (module == GNUPG_MODULE_NAME_GPG
551
0
      && (mode == GCRY_CIPHER_MODE_NONE
552
0
                      || mode == GCRY_CIPHER_MODE_CFB
553
0
                      || mode == GCRY_CIPHER_MODE_OCB)
554
0
      && ! producer);
555
0
  default:
556
0
    return 0;
557
0
  }
558
0
      log_assert (!"reached");
559
560
0
    default:
561
      /* The default policy is to allow all algorithms.  */
562
0
      return 1;
563
0
    }
564
565
0
  log_assert (!"reached");
566
0
}
567
568
569
/* Return true if DIGEST is compliant to the given COMPLIANCE mode.  */
570
int
571
gnupg_digest_is_compliant (enum gnupg_compliance_mode compliance,
572
                           digest_algo_t digest)
573
0
{
574
0
  if (! initialized)
575
0
    return 0;
576
577
0
  switch (compliance)
578
0
    {
579
0
    case CO_DE_VS:
580
0
      switch (digest)
581
0
  {
582
0
  case DIGEST_ALGO_SHA256:
583
0
  case DIGEST_ALGO_SHA384:
584
0
  case DIGEST_ALGO_SHA512:
585
0
    return 1;
586
0
  default:
587
0
    return 0;
588
0
  }
589
0
      log_assert (!"reached");
590
591
0
    default:
592
0
      return 0;
593
0
    }
594
595
0
  log_assert (!"reached");
596
0
}
597
598
599
/* Return true if DIGEST is allowed in the given COMPLIANCE mode.  If
600
 * PRODUCER is true, the predicate is evaluated for the producer, if
601
 * false for the consumer.  This way policies can be strict in what
602
 * they produce, and liberal in what they accept.  */
603
int
604
gnupg_digest_is_allowed (enum gnupg_compliance_mode compliance, int producer,
605
       digest_algo_t digest)
606
516
{
607
516
  if (! initialized)
608
516
    return 1;
609
610
0
  switch (compliance)
611
0
    {
612
0
    case CO_DE_VS:
613
0
      switch (digest)
614
0
  {
615
0
  case DIGEST_ALGO_SHA256:
616
0
  case DIGEST_ALGO_SHA384:
617
0
  case DIGEST_ALGO_SHA512:
618
0
    return 1;
619
0
  case DIGEST_ALGO_SHA1:
620
0
  case DIGEST_ALGO_SHA224:
621
0
  case DIGEST_ALGO_RMD160:
622
0
    return ! producer;
623
0
  case DIGEST_ALGO_MD5:
624
0
    return ! producer && module == GNUPG_MODULE_NAME_GPGSM;
625
0
  default:
626
0
    return 0;
627
0
  }
628
0
      log_assert (!"reached");
629
630
0
    default:
631
      /* The default policy is to allow all algorithms.  */
632
0
      return 1;
633
0
    }
634
635
0
  log_assert (!"reached");
636
0
}
637
638
639
/* Return True if the random number generator is compliant in
640
 * COMPLIANCE mode.  */
641
int
642
gnupg_rng_is_compliant (enum gnupg_compliance_mode compliance)
643
0
{
644
0
  int *result;
645
0
  int res;
646
647
  /* #warning debug code ahead */
648
  /* return 1; */
649
650
0
  result = get_compliance_cache (compliance, 1);
651
652
0
  if (result && *result != -1)
653
0
    res = *result; /* Use cached result.  */
654
0
  else if (compliance == CO_DE_VS)
655
0
    {
656
      /* We also check whether the library is at all compliant.  */
657
0
      res = gnupg_gcrypt_is_compliant (compliance);
658
659
      /* In DE_VS mode under Windows we also require that the JENT RNG
660
       * is active.  Check it here. */
661
#ifdef HAVE_W32_SYSTEM
662
      if (res == 1)
663
        {
664
          char *buf;
665
          const char *fields[5];
666
667
          buf = gcry_get_config (0, "rng-type");
668
          if (buf
669
              && split_fields_colon (buf, fields, DIM (fields)) >= 5
670
              && atoi (fields[4]) > 0)
671
            ; /* Field 5 > 0 := Jent is active.  */
672
          else
673
            result = 0;  /* Force non-compliance.  */
674
          gcry_free (buf);
675
        }
676
#endif /*HAVE_W32_SYSTEM*/
677
0
    }
678
0
  else
679
0
    res = 1;
680
681
0
  if (result)
682
0
    *result = res;
683
684
0
  return res;
685
0
}
686
687
688
/* Return true if the used Libgcrypt is compliant in COMPLIANCE
689
 * mode.  */
690
int
691
gnupg_gcrypt_is_compliant (enum gnupg_compliance_mode compliance)
692
0
{
693
0
  int *result;
694
0
  int res;
695
696
0
  result = get_compliance_cache (compliance, 0);
697
698
0
  if (result && *result != -1)
699
0
    res = *result; /* Use cached result.  */
700
0
  else if (compliance == CO_DE_VS)
701
0
    {
702
0
      int is19orlater = !!gcry_check_version ("1.9.0");
703
704
      /* A compliant version of GnuPG requires Libgcrypt >= 1.8.1 and
705
       * less than 1.9.0.  Version 1.9.0 requires a re-evaluation and
706
       * can thus not be used for de-vs.  */
707
0
      if (gcry_check_version ("1.8.1") && !is19orlater)
708
0
        res = 1;  /* Compliant version of Libgcrypt.  */
709
0
      else if (is19orlater)
710
0
        {
711
          /* Libgcrypt might be nice enough to tell us whether it is
712
           * compliant.  */
713
0
          char *buf;
714
0
          const char *fields[3];
715
716
0
          buf = gcry_get_config (0, "compliance");
717
0
          if (buf
718
0
              && split_fields_colon (buf, fields, DIM (fields)) >= 2
719
0
              && strstr (fields[1], "de-vs"))
720
0
            res = 1;  /* Compliant.  */
721
0
          else
722
0
            res = 0;  /* Non-compliant.  */
723
0
          gcry_free (buf);
724
0
        }
725
0
      else
726
0
        res = 0;  /* Non-compliant version of Libgcrypt.  */
727
0
    }
728
0
  else
729
0
    res = 1;
730
731
0
  if (result)
732
0
    *result = res;
733
734
0
  return res;
735
0
}
736
737
738
const char *
739
gnupg_status_compliance_flag (enum gnupg_compliance_mode compliance)
740
0
{
741
0
  switch (compliance)
742
0
    {
743
0
    case CO_GNUPG:
744
0
      return "8";
745
0
    case CO_RFC4880:
746
0
    case CO_RFC2440:
747
0
    case CO_PGP7:
748
0
    case CO_PGP8:
749
0
      log_assert (!"no status code assigned for this compliance mode");
750
0
    case CO_DE_VS:
751
0
      return get_assumed_de_vs_compliance ()? "2023" : "23";
752
0
    }
753
0
  log_assert (!"invalid compliance mode");
754
0
}
755
756
757
758
/* This function returns the value for the "manu" LibrePGP/rfc4880bis
759
 * notation.  See doc/DETAILS for a description.  This value is also
760
 * used for the manuNotation in X.509/CMS.  */
761
const char *
762
gnupg_manu_notation_value (enum gnupg_compliance_mode compliance)
763
0
{
764
0
  static char buffer[48];  /* Empty string indicates not yet initialized */
765
0
  static char buffer2[40];
766
767
0
  if (!*buffer)
768
0
    {
769
0
      char *buf;
770
0
      const char *s;
771
0
      int n;
772
0
      const char *fields[4];
773
0
      const char *vers1, *vers2;
774
0
      int vers1len, vers2len;
775
0
      int arch_id, os_id;
776
777
0
      arch_id = 0;
778
0
      buf = gcry_get_config (0, "cpu-arch");
779
0
      if (buf && (n=split_fields_colon (buf, fields, DIM (fields))) >= 2)
780
0
        {
781
0
          if (!strcmp (fields[1], "x86") && n > 2)
782
0
            {
783
0
              if (!strcmp (fields[2], "amd64"))
784
0
                arch_id = 2;
785
0
              else if (!strcmp (fields[2], "i386"))
786
0
                arch_id = 1;
787
0
            }
788
0
          else if (!strcmp (fields[1], "arm"))
789
0
            arch_id = 3;
790
0
        }
791
0
      gcry_free (buf);
792
#ifdef HAVE_W32_SYSTEM
793
      os_id = 1;
794
#elif defined(__linux__)
795
      os_id = 2;
796
#elif defined (__unix__) || defined(__APPLE__)
797
      os_id = 3;
798
#else
799
      os_id = 0;
800
#endif
801
0
      vers1 = PACKAGE_VERSION;
802
0
      for (s=vers1, n=0; *s; s++)
803
0
        if (*s=='.')
804
0
          if (++n == 2)
805
0
            break;
806
0
      vers1len = s-vers1;
807
808
0
      vers2 = gcry_check_version (NULL);
809
0
      for (s=vers2, n=0; *s; s++)
810
0
        if (*s=='.')
811
0
          if (++n == 2)
812
0
            break;
813
0
      vers2len = s-vers2;
814
815
0
      snprintf (buffer2, sizeof buffer2, "2,%.*s+%.*s,%d,%d",
816
0
                vers1len, vers1, vers2len, vers2, arch_id, os_id);
817
0
      snprintf (buffer, sizeof buffer, "%s,%d",
818
0
                buffer2, get_assumed_de_vs_compliance ()? 2023 : 23);
819
0
    }
820
821
0
  if (compliance == CO_DE_VS)
822
0
    return buffer;
823
0
  else
824
0
    return buffer2;
825
0
}
826
827
828
/* Parse the value of --compliance.  Returns the value corresponding
829
 * to the given STRING according to OPTIONS of size LENGTH, or -1
830
 * indicating that the lookup was unsuccessful, or the list of options
831
 * was printed.  If quiet is false, an additional hint to use 'help'
832
 * is printed on unsuccessful lookups.  */
833
int
834
gnupg_parse_compliance_option (const char *string,
835
             struct gnupg_compliance_option options[],
836
             size_t length,
837
             int quiet)
838
0
{
839
0
  size_t i;
840
841
0
  if (! ascii_strcasecmp (string, "help"))
842
0
    {
843
0
      log_info (_("valid values for option '%s':\n"), "--compliance");
844
0
      for (i = 0; i < length; i++)
845
0
        log_info ("  %s\n", options[i].keyword);
846
0
      return -1;
847
0
    }
848
849
0
  for (i = 0; i < length; i++)
850
0
    if (! ascii_strcasecmp (string, options[i].keyword))
851
0
      return options[i].value;
852
853
0
  log_error (_("invalid value for option '%s'\n"), "--compliance");
854
0
  if (! quiet)
855
0
    log_info (_("(use \"help\" to list choices)\n"));
856
0
  return -1;
857
0
}
858
859
860
/* Return the command line option for the given COMPLIANCE mode.  */
861
const char *
862
gnupg_compliance_option_string (enum gnupg_compliance_mode compliance)
863
0
{
864
0
  switch (compliance)
865
0
    {
866
0
    case CO_GNUPG:   return "--compliance=gnupg";
867
0
    case CO_RFC4880: return "--compliance=openpgp";
868
0
    case CO_RFC2440: return "--compliance=rfc2440";
869
0
    case CO_PGP7:    return "--compliance=pgp7";
870
0
    case CO_PGP8:    return "--compliance=pgp8";
871
0
    case CO_DE_VS:   return "--compliance=de-vs";
872
0
    }
873
874
0
  log_assert (!"invalid compliance mode");
875
0
}
876
877
878
/* Set additional infos for example taken from config files at startup.  */
879
void
880
gnupg_set_compliance_extra_info (unsigned int min_rsa)
881
0
{
882
0
  min_compliant_rsa_length = min_rsa;
883
0
}