Coverage Report

Created: 2026-04-27 06:29

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
                      || mode == GCRY_CIPHER_MODE_GCM);
494
0
      }
495
0
    log_assert (!"reached");
496
497
0
  default:
498
0
    return 0;
499
0
  }
500
0
      log_assert (!"reached");
501
502
0
    default:
503
0
      return 0;
504
0
    }
505
506
0
  log_assert (!"reached");
507
0
}
508
509
510
/* Return true if CIPHER is allowed in the given COMPLIANCE mode.  If
511
 * PRODUCER is true, the predicate is evaluated for the producer, if
512
 * false for the consumer.  This way policies can be strict in what
513
 * they produce, and liberal in what they accept.  */
514
int
515
gnupg_cipher_is_allowed (enum gnupg_compliance_mode compliance, int producer,
516
       cipher_algo_t cipher,
517
       enum gcry_cipher_modes mode)
518
0
{
519
0
  if (! initialized)
520
0
    return 1;
521
522
0
  switch (compliance)
523
0
    {
524
0
    case CO_DE_VS:
525
0
      switch (cipher)
526
0
  {
527
0
  case CIPHER_ALGO_AES:
528
0
  case CIPHER_ALGO_AES192:
529
0
  case CIPHER_ALGO_AES256:
530
0
  case CIPHER_ALGO_3DES:
531
0
    switch (module)
532
0
      {
533
0
      case GNUPG_MODULE_NAME_GPG:
534
0
        return (mode == GCRY_CIPHER_MODE_NONE
535
0
                      || mode == GCRY_CIPHER_MODE_CFB
536
0
                      || mode == GCRY_CIPHER_MODE_OCB);
537
0
      case GNUPG_MODULE_NAME_GPGSM:
538
0
        return (mode == GCRY_CIPHER_MODE_NONE
539
0
                      || mode == GCRY_CIPHER_MODE_CBC
540
0
                      || mode == GCRY_CIPHER_MODE_GCM);
541
0
      }
542
0
    log_assert (!"reached");
543
544
0
  case CIPHER_ALGO_BLOWFISH:
545
0
  case CIPHER_ALGO_CAMELLIA128:
546
0
  case CIPHER_ALGO_CAMELLIA192:
547
0
  case CIPHER_ALGO_CAMELLIA256:
548
0
  case CIPHER_ALGO_CAST5:
549
0
  case CIPHER_ALGO_IDEA:
550
0
  case CIPHER_ALGO_TWOFISH:
551
0
    return (module == GNUPG_MODULE_NAME_GPG
552
0
      && (mode == GCRY_CIPHER_MODE_NONE
553
0
                      || mode == GCRY_CIPHER_MODE_CFB
554
0
                      || mode == GCRY_CIPHER_MODE_OCB)
555
0
      && ! producer);
556
0
  default:
557
0
    return 0;
558
0
  }
559
0
      log_assert (!"reached");
560
561
0
    default:
562
      /* The default policy is to allow all algorithms.  */
563
0
      return 1;
564
0
    }
565
566
0
  log_assert (!"reached");
567
0
}
568
569
570
/* Return true if DIGEST is compliant to the given COMPLIANCE mode.  */
571
int
572
gnupg_digest_is_compliant (enum gnupg_compliance_mode compliance,
573
                           digest_algo_t digest)
574
0
{
575
0
  if (! initialized)
576
0
    return 0;
577
578
0
  switch (compliance)
579
0
    {
580
0
    case CO_DE_VS:
581
0
      switch (digest)
582
0
  {
583
0
  case DIGEST_ALGO_SHA256:
584
0
  case DIGEST_ALGO_SHA384:
585
0
  case DIGEST_ALGO_SHA512:
586
0
    return 1;
587
0
  default:
588
0
    return 0;
589
0
  }
590
0
      log_assert (!"reached");
591
592
0
    default:
593
0
      return 0;
594
0
    }
595
596
0
  log_assert (!"reached");
597
0
}
598
599
600
/* Return true if DIGEST is allowed in the given COMPLIANCE mode.  If
601
 * PRODUCER is true, the predicate is evaluated for the producer, if
602
 * false for the consumer.  This way policies can be strict in what
603
 * they produce, and liberal in what they accept.  */
604
int
605
gnupg_digest_is_allowed (enum gnupg_compliance_mode compliance, int producer,
606
       digest_algo_t digest)
607
10.3k
{
608
10.3k
  if (! initialized)
609
10.3k
    return 1;
610
611
0
  switch (compliance)
612
0
    {
613
0
    case CO_DE_VS:
614
0
      switch (digest)
615
0
  {
616
0
  case DIGEST_ALGO_SHA256:
617
0
  case DIGEST_ALGO_SHA384:
618
0
  case DIGEST_ALGO_SHA512:
619
0
    return 1;
620
0
  case DIGEST_ALGO_SHA1:
621
0
  case DIGEST_ALGO_SHA224:
622
0
  case DIGEST_ALGO_RMD160:
623
0
    return ! producer;
624
0
  case DIGEST_ALGO_MD5:
625
0
    return ! producer && module == GNUPG_MODULE_NAME_GPGSM;
626
0
  default:
627
0
    return 0;
628
0
  }
629
0
      log_assert (!"reached");
630
631
0
    default:
632
      /* The default policy is to allow all algorithms.  */
633
0
      return 1;
634
0
    }
635
636
0
  log_assert (!"reached");
637
0
}
638
639
640
/* Return True if the random number generator is compliant in
641
 * COMPLIANCE mode.  */
642
int
643
gnupg_rng_is_compliant (enum gnupg_compliance_mode compliance)
644
0
{
645
0
  int *result;
646
0
  int res;
647
648
  /* #warning debug code ahead */
649
  /* return 1; */
650
651
0
  result = get_compliance_cache (compliance, 1);
652
653
0
  if (result && *result != -1)
654
0
    res = *result; /* Use cached result.  */
655
0
  else if (compliance == CO_DE_VS)
656
0
    {
657
      /* We also check whether the library is at all compliant.  */
658
0
      res = gnupg_gcrypt_is_compliant (compliance);
659
660
      /* In DE_VS mode under Windows we also require that the JENT RNG
661
       * is active.  Check it here. */
662
#ifdef HAVE_W32_SYSTEM
663
      if (res == 1)
664
        {
665
          char *buf;
666
          const char *fields[5];
667
668
          buf = gcry_get_config (0, "rng-type");
669
          if (buf
670
              && split_fields_colon (buf, fields, DIM (fields)) >= 5
671
              && atoi (fields[4]) > 0)
672
            ; /* Field 5 > 0 := Jent is active.  */
673
          else
674
            result = 0;  /* Force non-compliance.  */
675
          gcry_free (buf);
676
        }
677
#endif /*HAVE_W32_SYSTEM*/
678
0
    }
679
0
  else
680
0
    res = 1;
681
682
0
  if (result)
683
0
    *result = res;
684
685
0
  return res;
686
0
}
687
688
689
/* Return true if the used Libgcrypt is compliant in COMPLIANCE
690
 * mode.  */
691
int
692
gnupg_gcrypt_is_compliant (enum gnupg_compliance_mode compliance)
693
0
{
694
0
  int *result;
695
0
  int res;
696
697
0
  result = get_compliance_cache (compliance, 0);
698
699
0
  if (result && *result != -1)
700
0
    res = *result; /* Use cached result.  */
701
0
  else if (compliance == CO_DE_VS)
702
0
    {
703
0
      int is19orlater = !!gcry_check_version ("1.9.0");
704
705
      /* A compliant version of GnuPG requires Libgcrypt >= 1.8.1 and
706
       * less than 1.9.0.  Version 1.9.0 requires a re-evaluation and
707
       * can thus not be used for de-vs.  */
708
0
      if (gcry_check_version ("1.8.1") && !is19orlater)
709
0
        res = 1;  /* Compliant version of Libgcrypt.  */
710
0
      else if (is19orlater)
711
0
        {
712
          /* Libgcrypt might be nice enough to tell us whether it is
713
           * compliant.  */
714
0
          char *buf;
715
0
          const char *fields[3];
716
717
0
          buf = gcry_get_config (0, "compliance");
718
0
          if (buf
719
0
              && split_fields_colon (buf, fields, DIM (fields)) >= 2
720
0
              && strstr (fields[1], "de-vs"))
721
0
            res = 1;  /* Compliant.  */
722
0
          else
723
0
            res = 0;  /* Non-compliant.  */
724
0
          gcry_free (buf);
725
0
        }
726
0
      else
727
0
        res = 0;  /* Non-compliant version of Libgcrypt.  */
728
0
    }
729
0
  else
730
0
    res = 1;
731
732
0
  if (result)
733
0
    *result = res;
734
735
0
  return res;
736
0
}
737
738
739
const char *
740
gnupg_status_compliance_flag (enum gnupg_compliance_mode compliance)
741
0
{
742
0
  switch (compliance)
743
0
    {
744
0
    case CO_GNUPG:
745
0
      return "8";
746
0
    case CO_RFC4880:
747
0
    case CO_RFC2440:
748
0
    case CO_PGP7:
749
0
    case CO_PGP8:
750
0
      log_assert (!"no status code assigned for this compliance mode");
751
0
    case CO_DE_VS:
752
0
      return get_assumed_de_vs_compliance ()? "2023" : "23";
753
0
    }
754
0
  log_assert (!"invalid compliance mode");
755
0
}
756
757
758
759
/* This function returns the value for the "manu" LibrePGP/rfc4880bis
760
 * notation.  See doc/DETAILS for a description.  This value is also
761
 * used for the manuNotation in X.509/CMS.  */
762
const char *
763
gnupg_manu_notation_value (enum gnupg_compliance_mode compliance)
764
0
{
765
0
  static char buffer[48];  /* Empty string indicates not yet initialized */
766
0
  static char buffer2[40];
767
768
0
  if (!*buffer)
769
0
    {
770
0
      char *buf;
771
0
      const char *s;
772
0
      int n;
773
0
      const char *fields[4];
774
0
      const char *vers1, *vers2;
775
0
      int vers1len, vers2len;
776
0
      int arch_id, os_id;
777
778
0
      arch_id = 0;
779
0
      buf = gcry_get_config (0, "cpu-arch");
780
0
      if (buf && (n=split_fields_colon (buf, fields, DIM (fields))) >= 2)
781
0
        {
782
0
          if (!strcmp (fields[1], "x86") && n > 2)
783
0
            {
784
0
              if (!strcmp (fields[2], "amd64"))
785
0
                arch_id = 2;
786
0
              else if (!strcmp (fields[2], "i386"))
787
0
                arch_id = 1;
788
0
            }
789
0
          else if (!strcmp (fields[1], "arm"))
790
0
            arch_id = 3;
791
0
        }
792
0
      gcry_free (buf);
793
#ifdef HAVE_W32_SYSTEM
794
      os_id = 1;
795
#elif defined(__linux__)
796
      os_id = 2;
797
#elif defined (__unix__) || defined(__APPLE__)
798
      os_id = 3;
799
#else
800
      os_id = 0;
801
#endif
802
0
      vers1 = PACKAGE_VERSION;
803
0
      for (s=vers1, n=0; *s; s++)
804
0
        if (*s=='.')
805
0
          if (++n == 2)
806
0
            break;
807
0
      vers1len = s-vers1;
808
809
0
      vers2 = gcry_check_version (NULL);
810
0
      for (s=vers2, n=0; *s; s++)
811
0
        if (*s=='.')
812
0
          if (++n == 2)
813
0
            break;
814
0
      vers2len = s-vers2;
815
816
0
      snprintf (buffer2, sizeof buffer2, "2,%.*s+%.*s,%d,%d",
817
0
                vers1len, vers1, vers2len, vers2, arch_id, os_id);
818
0
      snprintf (buffer, sizeof buffer, "%s,%d",
819
0
                buffer2, get_assumed_de_vs_compliance ()? 2023 : 23);
820
0
    }
821
822
0
  if (compliance == CO_DE_VS)
823
0
    return buffer;
824
0
  else
825
0
    return buffer2;
826
0
}
827
828
829
/* Parse the value of --compliance.  Returns the value corresponding
830
 * to the given STRING according to OPTIONS of size LENGTH, or -1
831
 * indicating that the lookup was unsuccessful, or the list of options
832
 * was printed.  If quiet is false, an additional hint to use 'help'
833
 * is printed on unsuccessful lookups.  */
834
int
835
gnupg_parse_compliance_option (const char *string,
836
             struct gnupg_compliance_option options[],
837
             size_t length,
838
             int quiet)
839
0
{
840
0
  size_t i;
841
842
0
  if (! ascii_strcasecmp (string, "help"))
843
0
    {
844
0
      log_info (_("valid values for option '%s':\n"), "--compliance");
845
0
      for (i = 0; i < length; i++)
846
0
        log_info ("  %s\n", options[i].keyword);
847
0
      return -1;
848
0
    }
849
850
0
  for (i = 0; i < length; i++)
851
0
    if (! ascii_strcasecmp (string, options[i].keyword))
852
0
      return options[i].value;
853
854
0
  log_error (_("invalid value for option '%s'\n"), "--compliance");
855
0
  if (! quiet)
856
0
    log_info (_("(use \"help\" to list choices)\n"));
857
0
  return -1;
858
0
}
859
860
861
/* Return the command line option for the given COMPLIANCE mode.  */
862
const char *
863
gnupg_compliance_option_string (enum gnupg_compliance_mode compliance)
864
0
{
865
0
  switch (compliance)
866
0
    {
867
0
    case CO_GNUPG:   return "--compliance=gnupg";
868
0
    case CO_RFC4880: return "--compliance=openpgp";
869
0
    case CO_RFC2440: return "--compliance=rfc2440";
870
0
    case CO_PGP7:    return "--compliance=pgp7";
871
0
    case CO_PGP8:    return "--compliance=pgp8";
872
0
    case CO_DE_VS:   return "--compliance=de-vs";
873
0
    }
874
875
0
  log_assert (!"invalid compliance mode");
876
0
}
877
878
879
/* Set additional infos for example taken from config files at startup.  */
880
void
881
gnupg_set_compliance_extra_info (unsigned int min_rsa)
882
0
{
883
0
  min_compliant_rsa_length = min_rsa;
884
0
}