Coverage Report

Created: 2022-12-08 06:09

/src/gnupg/common/compliance.c
Line
Count
Source (jump to first uncovered line)
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
/* This value is used by DSA and RSA checks in addition to the hard
44
 * coded length checks.  It allows to increase the required key length
45
 * using a confue file.  */
46
static unsigned int min_compliant_rsa_length;
47
48
/* Return the address of a compliance cache variable for COMPLIANCE.
49
 * If no such variable exists NULL is returned.  FOR_RNG returns the
50
 * cache variable for the RNG compliance check. */
51
static int *
52
get_compliance_cache (enum gnupg_compliance_mode compliance, int for_rng)
53
0
{
54
0
  static int r_gnupg   = -1, s_gnupg   = -1;
55
0
  static int r_rfc4880 = -1, s_rfc4880 = -1;
56
0
  static int r_rfc2440 = -1, s_rfc2440 = -1;
57
0
  static int r_pgp7    = -1, s_pgp7    = -1;
58
0
  static int r_pgp8    = -1, s_pgp8    = -1;
59
0
  static int r_de_vs   = -1, s_de_vs   = -1;
60
61
0
  int *ptr = NULL;
62
63
0
  switch (compliance)
64
0
    {
65
0
    case CO_GNUPG:   ptr = for_rng? &r_gnupg   : &s_gnupg  ; break;
66
0
    case CO_RFC4880: ptr = for_rng? &r_rfc4880 : &s_rfc4880; break;
67
0
    case CO_RFC2440: ptr = for_rng? &r_rfc2440 : &s_rfc2440; break;
68
0
    case CO_PGP7:    ptr = for_rng? &r_pgp7    : &s_pgp7   ; break;
69
0
    case CO_PGP8:    ptr = for_rng? &r_pgp8    : &s_pgp8   ; break;
70
0
    case CO_DE_VS:   ptr = for_rng? &r_de_vs   : &s_de_vs  ; break;
71
0
    }
72
73
0
  return ptr;
74
0
}
75
76
77
/* Initializes the module.  Must be called with the current
78
 * GNUPG_MODULE_NAME.  Checks a few invariants, and tunes the policies
79
 * for the given module.  */
80
void
81
gnupg_initialize_compliance (int gnupg_module_name)
82
1
{
83
1
  log_assert (! initialized);
84
85
  /* We accept both OpenPGP-style and gcrypt-style algorithm ids.
86
   * Assert that they are compatible.  */
87
0
  log_assert ((int) GCRY_PK_RSA          == (int) PUBKEY_ALGO_RSA);
88
0
  log_assert ((int) GCRY_PK_RSA_E        == (int) PUBKEY_ALGO_RSA_E);
89
0
  log_assert ((int) GCRY_PK_RSA_S        == (int) PUBKEY_ALGO_RSA_S);
90
0
  log_assert ((int) GCRY_PK_ELG_E        == (int) PUBKEY_ALGO_ELGAMAL_E);
91
0
  log_assert ((int) GCRY_PK_DSA          == (int) PUBKEY_ALGO_DSA);
92
0
  log_assert ((int) GCRY_PK_ECC          == (int) PUBKEY_ALGO_ECDH);
93
0
  log_assert ((int) GCRY_PK_ELG          == (int) PUBKEY_ALGO_ELGAMAL);
94
0
  log_assert ((int) GCRY_CIPHER_NONE     == (int) CIPHER_ALGO_NONE);
95
0
  log_assert ((int) GCRY_CIPHER_IDEA     == (int) CIPHER_ALGO_IDEA);
96
0
  log_assert ((int) GCRY_CIPHER_3DES     == (int) CIPHER_ALGO_3DES);
97
0
  log_assert ((int) GCRY_CIPHER_CAST5    == (int) CIPHER_ALGO_CAST5);
98
0
  log_assert ((int) GCRY_CIPHER_BLOWFISH == (int) CIPHER_ALGO_BLOWFISH);
99
0
  log_assert ((int) GCRY_CIPHER_AES      == (int) CIPHER_ALGO_AES);
100
0
  log_assert ((int) GCRY_CIPHER_AES192   == (int) CIPHER_ALGO_AES192);
101
0
  log_assert ((int) GCRY_CIPHER_AES256   == (int) CIPHER_ALGO_AES256);
102
0
  log_assert ((int) GCRY_CIPHER_TWOFISH  == (int) CIPHER_ALGO_TWOFISH);
103
0
  log_assert ((int) GCRY_MD_MD5          == (int) DIGEST_ALGO_MD5);
104
0
  log_assert ((int) GCRY_MD_SHA1         == (int) DIGEST_ALGO_SHA1);
105
0
  log_assert ((int) GCRY_MD_RMD160       == (int) DIGEST_ALGO_RMD160);
106
0
  log_assert ((int) GCRY_MD_SHA256       == (int) DIGEST_ALGO_SHA256);
107
0
  log_assert ((int) GCRY_MD_SHA384       == (int) DIGEST_ALGO_SHA384);
108
0
  log_assert ((int) GCRY_MD_SHA512       == (int) DIGEST_ALGO_SHA512);
109
0
  log_assert ((int) GCRY_MD_SHA224       == (int) DIGEST_ALGO_SHA224);
110
111
0
  switch (gnupg_module_name)
112
1
    {
113
0
    case GNUPG_MODULE_NAME_GPGSM:
114
1
    case GNUPG_MODULE_NAME_GPG:
115
1
      break;
116
117
0
    default:
118
0
      log_assert (!"no policies for this module");
119
1
    }
120
121
1
  module = gnupg_module_name;
122
1
  initialized = 1;
123
1
}
124
125
/* Return true if ALGO with a key of KEYLENGTH is compliant to the
126
 * given COMPLIANCE mode.  If KEY is not NULL, various bits of
127
 * information will be extracted from it.  If CURVENAME is not NULL, it
128
 * is assumed to be the already computed.  ALGO may be either an
129
 * OpenPGP-style pubkey_algo_t, or a gcrypt-style enum gcry_pk_algos,
130
 * both are compatible from the point of view of this function.  */
131
int
132
gnupg_pk_is_compliant (enum gnupg_compliance_mode compliance, int algo,
133
                       unsigned int algo_flags,
134
           gcry_mpi_t key[], unsigned int keylength,
135
                       const char *curvename)
136
0
{
137
0
  enum { is_rsa, is_dsa, is_elg, is_ecc } algotype;
138
0
  int result = 0;
139
140
0
  if (! initialized)
141
0
    return 0;
142
143
0
  switch (algo)
144
0
    {
145
0
    case PUBKEY_ALGO_RSA:
146
0
    case PUBKEY_ALGO_RSA_E:
147
0
    case PUBKEY_ALGO_RSA_S:
148
0
      algotype = is_rsa;
149
0
      break;
150
151
0
    case PUBKEY_ALGO_DSA:
152
0
      algotype = is_dsa;
153
0
      break;
154
155
0
    case PUBKEY_ALGO_ELGAMAL_E:
156
0
      algotype = is_elg;
157
0
      break;
158
159
0
    case PUBKEY_ALGO_ECDH:
160
0
    case PUBKEY_ALGO_ECDSA:
161
0
    case PUBKEY_ALGO_EDDSA:
162
0
      algotype = is_ecc;
163
0
      break;
164
165
0
    case PUBKEY_ALGO_ELGAMAL:
166
0
      return 0; /* Signing with Elgamal is not at all supported.  */
167
168
0
    default: /* Unknown.  */
169
0
      return 0;
170
0
    }
171
172
0
  if (compliance == CO_DE_VS)
173
0
    {
174
0
      char *curve = NULL;
175
176
0
      switch (algotype)
177
0
        {
178
0
        case is_elg:
179
0
          result = 0;
180
0
          break;
181
182
0
        case is_rsa:
183
0
          result = ((keylength == 2048
184
0
                     || keylength == 3072
185
0
                     || keylength == 4096)
186
0
                    && keylength >= min_compliant_rsa_length);
187
          /* Although rsaPSS was not part of the original evaluation
188
           * we got word that we can claim compliance.  */
189
0
          (void)algo_flags;
190
0
          break;
191
192
0
  case is_dsa:
193
0
    if (key)
194
0
      {
195
0
        size_t P = gcry_mpi_get_nbits (key[0]);
196
0
        size_t Q = gcry_mpi_get_nbits (key[1]);
197
0
        result = (Q == 256
198
0
      && (P == 2048 || P == 3072)
199
0
                        && P >= min_compliant_rsa_length);
200
0
      }
201
0
    break;
202
203
0
        case is_ecc:
204
0
          if (!curvename && key)
205
0
            {
206
0
              curve = openpgp_oid_to_str (key[0]);
207
0
              curvename = openpgp_oid_to_curve (curve, 0);
208
0
              if (!curvename)
209
0
                curvename = curve;
210
0
            }
211
212
0
          result = (curvename
213
0
                    && (algo == PUBKEY_ALGO_ECDH
214
0
                        || algo == PUBKEY_ALGO_ECDSA)
215
0
                    && (!strcmp (curvename, "brainpoolP256r1")
216
0
                        || !strcmp (curvename, "brainpoolP384r1")
217
0
                        || !strcmp (curvename, "brainpoolP512r1")));
218
0
          break;
219
220
0
        default:
221
0
          result = 0;
222
0
        }
223
0
      xfree (curve);
224
0
    }
225
0
  else
226
0
    {
227
0
      result = 1; /* Assume compliance.  */
228
0
    }
229
230
0
  return result;
231
0
}
232
233
234
/* Return true if ALGO with the given KEYLENGTH is allowed in the
235
 * given COMPLIANCE mode.  USE specifies for which use case the
236
 * predicate is evaluated.  This way policies can be strict in what
237
 * they produce, and liberal in what they accept.  */
238
int
239
gnupg_pk_is_allowed (enum gnupg_compliance_mode compliance,
240
         enum pk_use_case use, int algo,
241
                     unsigned int algo_flags, gcry_mpi_t key[],
242
         unsigned int keylength, const char *curvename)
243
0
{
244
0
  int result = 0;
245
246
0
  if (! initialized)
247
0
    return 1;
248
249
0
  switch (compliance)
250
0
    {
251
0
    case CO_DE_VS:
252
0
      switch (algo)
253
0
  {
254
0
  case PUBKEY_ALGO_RSA:
255
0
  case PUBKEY_ALGO_RSA_E:
256
0
  case PUBKEY_ALGO_RSA_S:
257
0
    switch (use)
258
0
      {
259
0
      case PK_USE_DECRYPTION:
260
0
      case PK_USE_VERIFICATION:
261
0
        result = 1;
262
0
              break;
263
0
      case PK_USE_ENCRYPTION:
264
0
      case PK_USE_SIGNING:
265
0
        result = ((keylength == 2048
266
0
                         || keylength == 3072
267
0
                         || keylength == 4096)
268
0
                        && keylength >= min_compliant_rsa_length);
269
0
              break;
270
0
      default:
271
0
        log_assert (!"reached");
272
0
      }
273
0
          (void)algo_flags;
274
0
    break;
275
276
0
  case PUBKEY_ALGO_DSA:
277
0
          if (use == PK_USE_VERIFICATION)
278
0
            result = 1;
279
0
    else if (use == PK_USE_SIGNING && key)
280
0
      {
281
0
        size_t P = gcry_mpi_get_nbits (key[0]);
282
0
        size_t Q = gcry_mpi_get_nbits (key[1]);
283
0
        result = (Q == 256
284
0
                        && (P == 2048 || P == 3072)
285
0
                        && keylength >= min_compliant_rsa_length);
286
0
            }
287
0
          break;
288
289
0
  case PUBKEY_ALGO_ELGAMAL:
290
0
  case PUBKEY_ALGO_ELGAMAL_E:
291
0
    result = (use == PK_USE_DECRYPTION);
292
0
          break;
293
294
0
  case PUBKEY_ALGO_ECDH:
295
0
    if (use == PK_USE_DECRYPTION)
296
0
            result = 1;
297
0
          else if (use == PK_USE_ENCRYPTION)
298
0
            {
299
0
              char *curve = NULL;
300
301
0
              if (!curvename && key)
302
0
                {
303
0
                  curve = openpgp_oid_to_str (key[0]);
304
0
                  curvename = openpgp_oid_to_curve (curve, 0);
305
0
                  if (!curvename)
306
0
                    curvename = curve;
307
0
                }
308
309
0
              result = (curvename
310
0
                        && (!strcmp (curvename, "brainpoolP256r1")
311
0
                            || !strcmp (curvename, "brainpoolP384r1")
312
0
                            || !strcmp (curvename, "brainpoolP512r1")));
313
314
0
              xfree (curve);
315
0
            }
316
0
          break;
317
318
0
  case PUBKEY_ALGO_ECDSA:
319
0
          if (use == PK_USE_VERIFICATION)
320
0
            result = 1;
321
0
          else
322
0
            {
323
0
              char *curve = NULL;
324
325
0
              if (! curvename && key)
326
0
        {
327
0
    curve = openpgp_oid_to_str (key[0]);
328
0
    curvename = openpgp_oid_to_curve (curve, 0);
329
0
    if (!curvename)
330
0
      curvename = curve;
331
0
        }
332
333
0
              result = (use == PK_USE_SIGNING
334
0
                         && curvename
335
0
                         && (!strcmp (curvename, "brainpoolP256r1")
336
0
                             || !strcmp (curvename, "brainpoolP384r1")
337
0
                             || !strcmp (curvename, "brainpoolP512r1")));
338
0
              xfree (curve);
339
0
            }
340
0
          break;
341
342
343
0
  case PUBKEY_ALGO_EDDSA:
344
0
    break;
345
346
0
  default:
347
0
    break;
348
0
  }
349
0
      break;
350
351
0
    default:
352
      /* The default policy is to allow all algorithms.  */
353
0
      result = 1;
354
0
    }
355
356
0
  return result;
357
0
}
358
359
360
/* Return true if (CIPHER, MODE) is compliant to the given COMPLIANCE mode.  */
361
int
362
gnupg_cipher_is_compliant (enum gnupg_compliance_mode compliance,
363
         cipher_algo_t cipher,
364
         enum gcry_cipher_modes mode)
365
0
{
366
0
  if (! initialized)
367
0
    return 0;
368
369
0
  switch (compliance)
370
0
    {
371
0
    case CO_DE_VS:
372
0
      switch (cipher)
373
0
  {
374
0
  case CIPHER_ALGO_AES:
375
0
  case CIPHER_ALGO_AES192:
376
0
  case CIPHER_ALGO_AES256:
377
0
  case CIPHER_ALGO_3DES:
378
0
    switch (module)
379
0
      {
380
0
      case GNUPG_MODULE_NAME_GPG:
381
0
        return mode == GCRY_CIPHER_MODE_CFB;
382
0
      case GNUPG_MODULE_NAME_GPGSM:
383
0
        return mode == GCRY_CIPHER_MODE_CBC;
384
0
      }
385
0
    log_assert (!"reached");
386
387
0
  default:
388
0
    return 0;
389
0
  }
390
0
      log_assert (!"reached");
391
392
0
    default:
393
0
      return 0;
394
0
    }
395
396
0
  log_assert (!"reached");
397
0
}
398
399
400
/* Return true if CIPHER is allowed in the given COMPLIANCE mode.  If
401
 * PRODUCER is true, the predicate is evaluated for the producer, if
402
 * false for the consumer.  This way policies can be strict in what
403
 * they produce, and liberal in what they accept.  */
404
int
405
gnupg_cipher_is_allowed (enum gnupg_compliance_mode compliance, int producer,
406
       cipher_algo_t cipher,
407
       enum gcry_cipher_modes mode)
408
0
{
409
0
  if (! initialized)
410
0
    return 1;
411
412
0
  switch (compliance)
413
0
    {
414
0
    case CO_DE_VS:
415
0
      switch (cipher)
416
0
  {
417
0
  case CIPHER_ALGO_AES:
418
0
  case CIPHER_ALGO_AES192:
419
0
  case CIPHER_ALGO_AES256:
420
0
  case CIPHER_ALGO_3DES:
421
0
    switch (module)
422
0
      {
423
0
      case GNUPG_MODULE_NAME_GPG:
424
0
        return (mode == GCRY_CIPHER_MODE_NONE
425
0
                      || mode == GCRY_CIPHER_MODE_CFB);
426
0
      case GNUPG_MODULE_NAME_GPGSM:
427
0
        return (mode == GCRY_CIPHER_MODE_NONE
428
0
                      || mode == GCRY_CIPHER_MODE_CBC
429
0
                      || (mode == GCRY_CIPHER_MODE_GCM && !producer));
430
0
      }
431
0
    log_assert (!"reached");
432
433
0
  case CIPHER_ALGO_BLOWFISH:
434
0
  case CIPHER_ALGO_CAMELLIA128:
435
0
  case CIPHER_ALGO_CAMELLIA192:
436
0
  case CIPHER_ALGO_CAMELLIA256:
437
0
  case CIPHER_ALGO_CAST5:
438
0
  case CIPHER_ALGO_IDEA:
439
0
  case CIPHER_ALGO_TWOFISH:
440
0
    return (module == GNUPG_MODULE_NAME_GPG
441
0
      && (mode == GCRY_CIPHER_MODE_NONE
442
0
                      || mode == GCRY_CIPHER_MODE_CFB)
443
0
      && ! producer);
444
0
  default:
445
0
    return 0;
446
0
  }
447
0
      log_assert (!"reached");
448
449
0
    default:
450
      /* The default policy is to allow all algorithms.  */
451
0
      return 1;
452
0
    }
453
454
0
  log_assert (!"reached");
455
0
}
456
457
458
/* Return true if DIGEST is compliant to the given COMPLIANCE mode.  */
459
int
460
gnupg_digest_is_compliant (enum gnupg_compliance_mode compliance,
461
                           digest_algo_t digest)
462
0
{
463
0
  if (! initialized)
464
0
    return 0;
465
466
0
  switch (compliance)
467
0
    {
468
0
    case CO_DE_VS:
469
0
      switch (digest)
470
0
  {
471
0
  case DIGEST_ALGO_SHA256:
472
0
  case DIGEST_ALGO_SHA384:
473
0
  case DIGEST_ALGO_SHA512:
474
0
    return 1;
475
0
  default:
476
0
    return 0;
477
0
  }
478
0
      log_assert (!"reached");
479
480
0
    default:
481
0
      return 0;
482
0
    }
483
484
0
  log_assert (!"reached");
485
0
}
486
487
488
/* Return true if DIGEST is allowed in the given COMPLIANCE mode.  If
489
 * PRODUCER is true, the predicate is evaluated for the producer, if
490
 * false for the consumer.  This way policies can be strict in what
491
 * they produce, and liberal in what they accept.  */
492
int
493
gnupg_digest_is_allowed (enum gnupg_compliance_mode compliance, int producer,
494
       digest_algo_t digest)
495
3.12k
{
496
3.12k
  if (! initialized)
497
0
    return 1;
498
499
3.12k
  switch (compliance)
500
3.12k
    {
501
0
    case CO_DE_VS:
502
0
      switch (digest)
503
0
  {
504
0
  case DIGEST_ALGO_SHA256:
505
0
  case DIGEST_ALGO_SHA384:
506
0
  case DIGEST_ALGO_SHA512:
507
0
    return 1;
508
0
  case DIGEST_ALGO_SHA1:
509
0
  case DIGEST_ALGO_SHA224:
510
0
  case DIGEST_ALGO_RMD160:
511
0
    return ! producer;
512
0
  case DIGEST_ALGO_MD5:
513
0
    return ! producer && module == GNUPG_MODULE_NAME_GPGSM;
514
0
  default:
515
0
    return 0;
516
0
  }
517
0
      log_assert (!"reached");
518
519
3.12k
    default:
520
      /* The default policy is to allow all algorithms.  */
521
3.12k
      return 1;
522
3.12k
    }
523
524
0
  log_assert (!"reached");
525
0
}
526
527
528
/* Return True if the random number generator is compliant in
529
 * COMPLIANCE mode.  */
530
int
531
gnupg_rng_is_compliant (enum gnupg_compliance_mode compliance)
532
0
{
533
0
  int *result;
534
0
  int res;
535
536
0
  result = get_compliance_cache (compliance, 1);
537
538
0
  if (result && *result != -1)
539
0
    res = *result; /* Use cached result.  */
540
0
  else if (compliance == CO_DE_VS)
541
0
    {
542
      /* We also check whether the library is at all compliant.  */
543
0
      res = gnupg_gcrypt_is_compliant (compliance);
544
545
      /* In DE_VS mode under Windows we also require that the JENT RNG
546
       * is active.  Check it here. */
547
#ifdef HAVE_W32_SYSTEM
548
      if (res == 1)
549
        {
550
          char *buf;
551
          const char *fields[5];
552
553
          buf = gcry_get_config (0, "rng-type");
554
          if (buf
555
              && split_fields_colon (buf, fields, DIM (fields)) >= 5
556
              && atoi (fields[4]) > 0)
557
            ; /* Field 5 > 0 := Jent is active.  */
558
          else
559
            result = 0;  /* Force non-compliance.  */
560
          gcry_free (buf);
561
        }
562
#endif /*HAVE_W32_SYSTEM*/
563
0
    }
564
0
  else
565
0
    res = 1;
566
567
0
  if (result)
568
0
    *result = res;
569
570
0
  return res;
571
0
}
572
573
574
/* Return true if the used Libgcrypt is compliant in COMPLIANCE
575
 * mode.  */
576
int
577
gnupg_gcrypt_is_compliant (enum gnupg_compliance_mode compliance)
578
0
{
579
0
  int *result;
580
0
  int res;
581
582
0
  result = get_compliance_cache (compliance, 0);
583
584
0
  if (result && *result != -1)
585
0
    res = *result; /* Use cached result.  */
586
0
  else if (compliance == CO_DE_VS)
587
0
    {
588
0
      int is19orlater = !!gcry_check_version ("1.9.0");
589
590
      /* A compliant version of GnuPG requires Libgcrypt >= 1.8.1 and
591
       * less than 1.9.0.  Version 1.9.0 requires a re-evaluation and
592
       * can thus not be used for de-vs.  */
593
0
      if (gcry_check_version ("1.8.1") && !is19orlater)
594
0
        res = 1;  /* Compliant version of Libgcrypt.  */
595
0
      else if (is19orlater)
596
0
        {
597
          /* Libgcrypt might be nice enough to tell us whether it is
598
           * compliant.  */
599
0
          char *buf;
600
0
          const char *fields[3];
601
602
0
          buf = gcry_get_config (0, "compliance");
603
0
          if (buf
604
0
              && split_fields_colon (buf, fields, DIM (fields)) >= 2
605
0
              && strstr (fields[1], "de-vs"))
606
0
            res = 1;  /* Compliant.  */
607
0
          else
608
0
            res = 0;  /* Non-compliant.  */
609
0
          gcry_free (buf);
610
0
        }
611
0
      else
612
0
        res = 0;  /* Non-compliant version of Libgcrypt.  */
613
0
    }
614
0
  else
615
0
    res = 1;
616
617
0
  if (result)
618
0
    *result = res;
619
620
0
  return res;
621
0
}
622
623
624
const char *
625
gnupg_status_compliance_flag (enum gnupg_compliance_mode compliance)
626
0
{
627
0
  switch (compliance)
628
0
    {
629
0
    case CO_GNUPG:
630
0
      return "8";
631
0
    case CO_RFC4880:
632
0
    case CO_RFC2440:
633
0
    case CO_PGP7:
634
0
    case CO_PGP8:
635
0
      log_assert (!"no status code assigned for this compliance mode");
636
0
    case CO_DE_VS:
637
0
      return "23";
638
0
    }
639
0
  log_assert (!"invalid compliance mode");
640
0
}
641
642
643
/* Parse the value of --compliance.  Returns the value corresponding
644
 * to the given STRING according to OPTIONS of size LENGTH, or -1
645
 * indicating that the lookup was unsuccessful, or the list of options
646
 * was printed.  If quiet is false, an additional hint to use 'help'
647
 * is printed on unsuccessful lookups.  */
648
int
649
gnupg_parse_compliance_option (const char *string,
650
             struct gnupg_compliance_option options[],
651
             size_t length,
652
             int quiet)
653
0
{
654
0
  size_t i;
655
656
0
  if (! ascii_strcasecmp (string, "help"))
657
0
    {
658
0
      log_info (_("valid values for option '%s':\n"), "--compliance");
659
0
      for (i = 0; i < length; i++)
660
0
        log_info ("  %s\n", options[i].keyword);
661
0
      return -1;
662
0
    }
663
664
0
  for (i = 0; i < length; i++)
665
0
    if (! ascii_strcasecmp (string, options[i].keyword))
666
0
      return options[i].value;
667
668
0
  log_error (_("invalid value for option '%s'\n"), "--compliance");
669
0
  if (! quiet)
670
0
    log_info (_("(use \"help\" to list choices)\n"));
671
0
  return -1;
672
0
}
673
674
675
/* Return the command line option for the given COMPLIANCE mode.  */
676
const char *
677
gnupg_compliance_option_string (enum gnupg_compliance_mode compliance)
678
0
{
679
0
  switch (compliance)
680
0
    {
681
0
    case CO_GNUPG:   return "--compliance=gnupg";
682
0
    case CO_RFC4880: return "--compliance=openpgp";
683
0
    case CO_RFC2440: return "--compliance=rfc2440";
684
0
    case CO_PGP7:    return "--compliance=pgp7";
685
0
    case CO_PGP8:    return "--compliance=pgp8";
686
0
    case CO_DE_VS:   return "--compliance=de-vs";
687
0
    }
688
689
0
  log_assert (!"invalid compliance mode");
690
0
}
691
692
693
/* Set additional infos for example taken from config files at startup.  */
694
void
695
gnupg_set_compliance_extra_info (unsigned int min_rsa)
696
0
{
697
0
  min_compliant_rsa_length = min_rsa;
698
0
}