Coverage Report

Created: 2026-06-10 07:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/p11-kit/common/attrs.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2012, Redhat Inc.
3
 * Copyright (c) 2011, Collabora Ltd.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 *
9
 *     * Redistributions of source code must retain the above
10
 *       copyright notice, this list of conditions and the
11
 *       following disclaimer.
12
 *     * Redistributions in binary form must reproduce the
13
 *       above copyright notice, this list of conditions and
14
 *       the following disclaimer in the documentation and/or
15
 *       other materials provided with the distribution.
16
 *     * The names of contributors to this software may not be
17
 *       used to endorse or promote products derived from this
18
 *       software without specific prior written permission.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30
 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31
 * DAMAGE.
32
 *
33
 * Author: Stef Walter <stefw@collabora.co.uk>
34
 */
35
36
#include "config.h"
37
38
#include "attrs.h"
39
#include "buffer.h"
40
#include "compat.h"
41
#include "constants.h"
42
#include "debug.h"
43
#include "hash.h"
44
#include "pkcs11.h"
45
#include "pkcs11i.h"
46
#include "pkcs11x.h"
47
48
#include <assert.h>
49
#include <stdarg.h>
50
#include <stdio.h>
51
#include <stdint.h>
52
#include <stdlib.h>
53
#include <string.h>
54
55
#define ELEMS(x) (sizeof (x) / sizeof (x[0]))
56
57
bool
58
p11_attrs_terminator (const CK_ATTRIBUTE *attrs)
59
13.5k
{
60
13.5k
  return (attrs == NULL || attrs->type == CKA_INVALID);
61
13.5k
}
62
63
CK_ULONG
64
p11_attrs_count (const CK_ATTRIBUTE *attrs)
65
1.72k
{
66
1.72k
  CK_ULONG count;
67
68
1.72k
  if (attrs == NULL)
69
860
    return 0;
70
71
6.36k
  for (count = 0; !p11_attrs_terminator (attrs); count++, attrs++);
72
73
860
  return count;
74
1.72k
}
75
76
void
77
p11_attrs_free (void *attrs)
78
855
{
79
855
  CK_ATTRIBUTE *ats = attrs;
80
855
  int i;
81
82
855
  if (attrs == NULL)
83
0
    return;
84
85
6.32k
  for (i = 0; !p11_attrs_terminator (ats + i); i++)
86
5.47k
    p11_attr_clear (&ats[i]);
87
855
  free (ats);
88
855
}
89
90
/* Call to this function always invalidates pointer to `attrs`
91
 */
92
static CK_ATTRIBUTE *
93
attrs_build (CK_ATTRIBUTE *attrs,
94
             CK_ULONG count_to_add,
95
             bool take_values,
96
             bool override,
97
             CK_ATTRIBUTE * (*generator) (void *),
98
             void *state)
99
860
{
100
860
  CK_ATTRIBUTE *attr;
101
860
  CK_ATTRIBUTE *add;
102
860
  CK_ULONG current;
103
860
  CK_ULONG at;
104
860
  CK_ULONG j;
105
860
  CK_ULONG i;
106
860
  size_t length;
107
860
  void *new_memory;
108
109
  /* How many attributes we already have */
110
860
  current = p11_attrs_count (attrs);
111
112
  /* Reallocate for how many we need */
113
860
  length = current + count_to_add;
114
860
  if (current > length || length >= SIZE_MAX) {
115
0
    p11_attrs_free (attrs);
116
0
    return_val_if_reached (NULL);
117
0
  }
118
860
  new_memory = reallocarray (attrs, length + 1, sizeof (CK_ATTRIBUTE));
119
860
  if (new_memory == NULL) {
120
0
    p11_attrs_free (attrs);
121
0
    return_val_if_reached (NULL);
122
0
  }
123
860
  attrs = new_memory;
124
125
860
  at = current;
126
6.36k
  for (i = 0; i < count_to_add; i++) {
127
5.50k
    add = (generator) (state);
128
129
    /* Skip with invalid type */
130
5.50k
    if (!add || add->type == CKA_INVALID)
131
0
      continue;
132
133
5.50k
    attr = NULL;
134
135
    /* Do we have this attribute? */
136
5.50k
    for (j = 0; attr == NULL && j < current; j++) {
137
0
      if (attrs[j].type == add->type) {
138
0
        attr = attrs + j;
139
0
        break;
140
0
      }
141
0
    }
142
143
    /* The attribute doesn't exist */
144
5.50k
    if (attr == NULL) {
145
5.50k
      attr = attrs + at;
146
5.50k
      at++;
147
148
    /* The attribute exists and we're not overriding */
149
5.50k
    } else if (!override) {
150
0
      if (take_values)
151
0
        p11_attr_clear (add);
152
0
      continue;
153
154
    /* The attribute exists but we're overriding */
155
0
    } else {
156
0
      p11_attr_clear (attr);
157
0
    }
158
159
5.50k
    if (take_values) {
160
0
      memcpy (attr, add, sizeof (CK_ATTRIBUTE));
161
5.50k
    } else if (!p11_attr_copy (attr, add)) {
162
0
      attrs[at].type = CKA_INVALID;
163
0
      p11_attrs_free (attrs);
164
0
      return_val_if_reached (NULL);
165
0
    }
166
5.50k
  }
167
168
  /* Mark this as the end */
169
860
  attrs[at].type = CKA_INVALID;
170
860
  assert (p11_attrs_terminator (attrs + at));
171
860
  return attrs;
172
860
}
173
174
static CK_ATTRIBUTE *
175
vararg_generator (void *state)
176
0
{
177
0
  va_list *va = state;
178
0
  return va_arg (*va, CK_ATTRIBUTE *);
179
0
}
180
181
CK_ATTRIBUTE *
182
p11_attrs_build (CK_ATTRIBUTE *attrs,
183
                 ...)
184
0
{
185
0
  CK_ULONG count;
186
0
  va_list va;
187
188
0
  count = 0UL;
189
0
  va_start (va, attrs);
190
0
  while (va_arg (va, CK_ATTRIBUTE *))
191
0
    count++;
192
0
  va_end (va);
193
194
0
  va_start (va, attrs);
195
0
  attrs = attrs_build (attrs, count, false, true,
196
0
                       vararg_generator, &va);
197
0
  va_end (va);
198
199
0
  return attrs;
200
0
}
201
202
static CK_ATTRIBUTE *
203
template_generator (void *state)
204
5.50k
{
205
5.50k
  CK_ATTRIBUTE **template = state;
206
5.50k
  return (*template)++;
207
5.50k
}
208
209
CK_ATTRIBUTE *
210
p11_attrs_buildn (CK_ATTRIBUTE *attrs,
211
                  const CK_ATTRIBUTE *add,
212
                  CK_ULONG count)
213
860
{
214
860
  return attrs_build (attrs, count, false, true,
215
860
                      template_generator, &add);
216
860
}
217
218
CK_ATTRIBUTE *
219
p11_attrs_take (CK_ATTRIBUTE *attrs,
220
                CK_ATTRIBUTE_TYPE type,
221
                CK_VOID_PTR value,
222
                CK_ULONG length)
223
0
{
224
0
  CK_ATTRIBUTE attr = { type, value, length };
225
0
  CK_ATTRIBUTE *add = &attr;
226
0
  return attrs_build (attrs, 1, true, true,
227
0
                      template_generator, &add);
228
0
}
229
230
CK_ATTRIBUTE *
231
p11_attrs_merge (CK_ATTRIBUTE *attrs,
232
                 CK_ATTRIBUTE *merge,
233
                 bool replace)
234
0
{
235
0
  CK_ATTRIBUTE *ptr;
236
0
  CK_ULONG count;
237
238
0
  if (attrs == NULL || attrs == merge)
239
0
    return merge;
240
241
0
  ptr = merge;
242
0
  count = p11_attrs_count (merge);
243
244
0
  attrs = attrs_build (attrs, count, true, replace,
245
0
                       template_generator, &ptr);
246
0
  if (attrs == NULL) {
247
0
    p11_attrs_free (merge);
248
0
    return_val_if_reached (NULL);
249
0
  }
250
251
  /*
252
   * Since we're supposed to own the merge attributes,
253
   * free the container array.
254
   */
255
0
  free (merge);
256
0
  return attrs;
257
0
}
258
259
CK_ATTRIBUTE *
260
p11_attrs_dup (const CK_ATTRIBUTE *attrs)
261
860
{
262
860
  CK_ULONG count;
263
264
860
  count = p11_attrs_count (attrs);
265
860
  return p11_attrs_buildn (NULL, attrs, count);
266
860
}
267
268
CK_ATTRIBUTE *
269
p11_attrs_find (CK_ATTRIBUTE *attrs,
270
                CK_ATTRIBUTE_TYPE type)
271
0
{
272
0
  CK_ULONG i;
273
274
0
  for (i = 0; !p11_attrs_terminator (attrs + i); i++) {
275
0
    if (attrs[i].type == type)
276
0
      return attrs + i;
277
0
  }
278
279
0
  return NULL;
280
0
}
281
282
CK_ATTRIBUTE *
283
p11_attrs_findn (CK_ATTRIBUTE *attrs,
284
                 CK_ULONG count,
285
                 CK_ATTRIBUTE_TYPE type)
286
0
{
287
0
  CK_ULONG i;
288
289
0
  for (i = 0; i < count; i++) {
290
0
    if (attrs[i].type == type)
291
0
      return attrs + i;
292
0
  }
293
294
0
  return NULL;
295
0
}
296
297
bool
298
p11_attrs_find_bool (const CK_ATTRIBUTE *attrs,
299
                     CK_ATTRIBUTE_TYPE type,
300
                     CK_BBOOL *value)
301
0
{
302
0
  CK_ULONG i;
303
304
0
  for (i = 0; !p11_attrs_terminator (attrs + i); i++) {
305
0
    if (attrs[i].type == type &&
306
0
        attrs[i].ulValueLen == sizeof (CK_BBOOL) &&
307
0
        attrs[i].pValue != NULL) {
308
0
      *value = *((CK_BBOOL *)attrs[i].pValue);
309
0
      return true;
310
0
    }
311
0
  }
312
313
0
  return false;
314
0
}
315
316
bool
317
p11_attrs_findn_bool (const CK_ATTRIBUTE *attrs,
318
                      CK_ULONG count,
319
                      CK_ATTRIBUTE_TYPE type,
320
                      CK_BBOOL *value)
321
0
{
322
0
  CK_ULONG i;
323
324
0
  for (i = 0; i < count; i++) {
325
0
    if (attrs[i].type == type &&
326
0
        attrs[i].ulValueLen == sizeof (CK_BBOOL) &&
327
0
        attrs[i].pValue != NULL) {
328
0
      *value = *((CK_BBOOL *)attrs[i].pValue);
329
0
      return true;
330
0
    }
331
0
  }
332
333
0
  return false;
334
0
}
335
336
bool
337
p11_attrs_find_ulong (const CK_ATTRIBUTE *attrs,
338
                      CK_ATTRIBUTE_TYPE type,
339
                      CK_ULONG *value)
340
0
{
341
0
  CK_ULONG i;
342
343
0
  for (i = 0; !p11_attrs_terminator (attrs + i); i++) {
344
0
    if (attrs[i].type == type &&
345
0
        attrs[i].ulValueLen == sizeof (CK_ULONG) &&
346
0
        attrs[i].pValue != NULL) {
347
0
      *value = *((CK_ULONG *)attrs[i].pValue);
348
0
      return true;
349
0
    }
350
0
  }
351
352
0
  return false;
353
0
}
354
355
bool
356
p11_attrs_findn_ulong (const CK_ATTRIBUTE *attrs,
357
                       CK_ULONG count,
358
                       CK_ATTRIBUTE_TYPE type,
359
                       CK_ULONG *value)
360
0
{
361
0
  CK_ULONG i;
362
363
0
  for (i = 0; i < count; i++) {
364
0
    if (attrs[i].type == type &&
365
0
        attrs[i].ulValueLen == sizeof (CK_ULONG) &&
366
0
        attrs[i].pValue != NULL) {
367
0
      *value = *((CK_ULONG *)attrs[i].pValue);
368
0
      return true;
369
0
    }
370
0
  }
371
372
0
  return false;
373
0
}
374
375
void *
376
p11_attrs_find_value (CK_ATTRIBUTE *attrs,
377
                      CK_ATTRIBUTE_TYPE type,
378
                      size_t *length)
379
0
{
380
0
  CK_ULONG i;
381
382
0
  for (i = 0; !p11_attrs_terminator (attrs + i); i++) {
383
0
    if (attrs[i].type == type &&
384
0
        attrs[i].ulValueLen != 0 &&
385
0
        attrs[i].ulValueLen != (CK_ULONG)-1 &&
386
0
        attrs[i].pValue != NULL) {
387
0
      if (length)
388
0
        *length = attrs[i].ulValueLen;
389
0
      return attrs[i].pValue;
390
0
    }
391
0
  }
392
393
0
  return NULL;
394
0
}
395
396
CK_ATTRIBUTE *
397
p11_attrs_find_valid (CK_ATTRIBUTE *attrs,
398
                      CK_ATTRIBUTE_TYPE type)
399
0
{
400
0
  CK_ULONG i;
401
402
0
  for (i = 0; !p11_attrs_terminator (attrs + i); i++) {
403
0
    if (attrs[i].type == type &&
404
0
        attrs[i].pValue != NULL &&
405
0
        attrs[i].ulValueLen != 0 &&
406
0
        attrs[i].ulValueLen != (CK_ULONG)-1)
407
0
      return attrs + i;
408
0
  }
409
410
0
  return NULL;
411
0
}
412
413
bool
414
p11_attrs_remove (CK_ATTRIBUTE *attrs,
415
                  CK_ATTRIBUTE_TYPE type)
416
0
{
417
0
  CK_ULONG count;
418
0
  CK_ULONG i;
419
420
0
  count = p11_attrs_count (attrs);
421
0
  for (i = 0; i < count; i++) {
422
0
    if (attrs[i].type == type)
423
0
      break;
424
0
  }
425
426
0
  if (i == count)
427
0
    return false;
428
429
0
  if (attrs[i].pValue)
430
0
    p11_attr_clear (&attrs[i]);
431
432
0
  memmove (attrs + i, attrs + i + 1, (count - (i + 1)) * sizeof (CK_ATTRIBUTE));
433
0
  attrs[count - 1].type = CKA_INVALID;
434
0
  return true;
435
0
}
436
437
void
438
p11_attrs_purge (CK_ATTRIBUTE *attrs)
439
0
{
440
0
  int in, out;
441
442
0
  for (in = 0, out = 0; !p11_attrs_terminator (attrs + in); in++) {
443
0
    if (attrs[in].ulValueLen == (CK_ULONG)-1) {
444
0
      free (attrs[in].pValue);
445
0
      attrs[in].pValue = NULL;
446
0
      attrs[in].ulValueLen = 0;
447
0
    } else {
448
0
      if (in != out)
449
0
        memcpy (attrs + out, attrs + in, sizeof (CK_ATTRIBUTE));
450
0
      out++;
451
0
    }
452
0
  }
453
454
0
  attrs[out].type = CKA_INVALID;
455
0
  assert (p11_attrs_terminator (attrs + out));
456
457
0
}
458
459
bool
460
p11_attrs_match (const CK_ATTRIBUTE *attrs,
461
                 const CK_ATTRIBUTE *match)
462
0
{
463
0
  CK_ATTRIBUTE *attr;
464
465
0
  for (; !p11_attrs_terminator (match); match++) {
466
0
    attr = p11_attrs_find ((CK_ATTRIBUTE *)attrs, match->type);
467
0
    if (!attr)
468
0
      return false;
469
0
    if (!p11_attr_equal (attr, match))
470
0
      return false;
471
0
  }
472
473
0
  return true;
474
0
}
475
476
bool
477
p11_attrs_matchn (const CK_ATTRIBUTE *attrs,
478
                  const CK_ATTRIBUTE *match,
479
                  CK_ULONG count)
480
0
{
481
0
  CK_ATTRIBUTE *attr;
482
0
  CK_ULONG i;
483
484
0
  for (i = 0; i < count; i++) {
485
0
    attr = p11_attrs_find ((CK_ATTRIBUTE *)attrs, match[i].type);
486
0
    if (!attr)
487
0
      return false;
488
0
    if (!p11_attr_equal (attr, match + i))
489
0
      return false;
490
0
  }
491
492
0
  return true;
493
494
0
}
495
496
497
bool
498
p11_attr_match_value (const CK_ATTRIBUTE *attr,
499
                      const void *value,
500
                      ssize_t length)
501
0
{
502
0
  if (length < 0)
503
0
    length = strlen (value);
504
0
  return (attr != NULL &&
505
0
          attr->ulValueLen == length &&
506
0
          (attr->pValue == value ||
507
0
           (attr->pValue && value &&
508
0
            memcmp (attr->pValue, value, attr->ulValueLen) == 0)));
509
0
}
510
511
bool
512
p11_attr_equal (const void *v1,
513
                const void *v2)
514
0
{
515
0
  const CK_ATTRIBUTE *one = v1;
516
0
  const CK_ATTRIBUTE *two = v2;
517
518
0
  return (one == two ||
519
0
    (one && two && one->type == two->type &&
520
0
     p11_attr_match_value (one, two->pValue, two->ulValueLen)));
521
0
}
522
523
unsigned int
524
p11_attr_hash (const void *data)
525
0
{
526
0
  const CK_ATTRIBUTE *attr = data;
527
0
  uint32_t hash = 0;
528
529
0
  if (attr != NULL) {
530
0
    p11_hash_murmur3 (&hash,
531
0
                      &attr->type, sizeof (attr->type),
532
0
                      attr->pValue, (size_t)attr->ulValueLen,
533
0
                      NULL);
534
0
  }
535
536
0
  return hash;
537
0
}
538
539
bool
540
p11_attr_copy (CK_ATTRIBUTE *dst, const CK_ATTRIBUTE *src)
541
6.02k
{
542
6.02k
  return_val_if_fail (dst != NULL, false);
543
6.02k
  return_val_if_fail (src != NULL, false);
544
545
6.02k
  memcpy (dst, src, sizeof (CK_ATTRIBUTE));
546
547
6.02k
  if (src->pValue == NULL)
548
0
    return true;
549
550
6.02k
  dst->pValue = malloc (src->ulValueLen == 0 ? 1 : src->ulValueLen);
551
6.02k
  return_val_if_fail (dst->pValue != NULL, false);
552
553
6.02k
  assert (dst->ulValueLen >= src->ulValueLen);
554
555
6.02k
  if (IS_ATTRIBUTE_ARRAY (src)) {
556
172
    CK_ATTRIBUTE *child_dst;
557
172
    const CK_ATTRIBUTE *child_src;
558
172
    size_t i;
559
560
172
    for (i = 0, child_dst = dst->pValue, child_src = src->pValue;
561
688
         i < src->ulValueLen / sizeof (CK_ATTRIBUTE);
562
516
         i++, child_dst++, child_src++) {
563
516
      if (!p11_attr_copy (child_dst, child_src)) {
564
        /* Free the copied children */
565
0
        for (size_t j = 0; j < i; j++)
566
0
          p11_attr_clear (child_dst + j);
567
0
        free (dst->pValue);
568
0
        dst->pValue = NULL;
569
0
        return false;
570
0
      }
571
516
    }
572
5.84k
  } else {
573
5.84k
    memcpy (dst->pValue, src->pValue, src->ulValueLen);
574
5.84k
  }
575
576
6.02k
  return true;
577
6.02k
}
578
579
void
580
p11_attr_clear (CK_ATTRIBUTE *attr)
581
5.98k
{
582
5.98k
  if (attr == NULL || attr->pValue == NULL)
583
0
    return;
584
585
5.98k
  if (IS_ATTRIBUTE_ARRAY (attr)) {
586
171
    CK_ATTRIBUTE *child;
587
171
    size_t i;
588
589
171
    for (i = 0, child = attr->pValue;
590
684
         i < attr->ulValueLen / sizeof (CK_ATTRIBUTE);
591
513
         i++, child++)
592
513
      p11_attr_clear (child);
593
171
  }
594
5.98k
  free (attr->pValue);
595
5.98k
  attr->pValue = NULL;
596
5.98k
}
597
598
static void
599
buffer_append_printf (p11_buffer *buffer,
600
                      const char *format,
601
                      ...) GNUC_PRINTF(2, 3);
602
603
static void
604
buffer_append_printf (p11_buffer *buffer,
605
                      const char *format,
606
                      ...)
607
0
{
608
0
  char *string;
609
0
  va_list va;
610
611
0
  va_start (va, format);
612
0
  if (vasprintf (&string, format, va) < 0) {
613
0
    va_end (va);
614
0
    return_if_reached ();
615
0
  }
616
0
  va_end (va);
617
618
0
  p11_buffer_add (buffer, string, -1);
619
0
  free (string);
620
0
}
621
622
static bool
623
attribute_is_ulong_of_type (const CK_ATTRIBUTE *attr,
624
                            CK_ULONG type)
625
0
{
626
0
  if (attr->type != type)
627
0
    return false;
628
0
  if (attr->ulValueLen != sizeof (CK_ULONG))
629
0
    return false;
630
0
  if (!attr->pValue)
631
0
    return false;
632
0
  return true;
633
0
}
634
635
static bool
636
attribute_is_trust_value (const CK_ATTRIBUTE *attr)
637
0
{
638
0
  switch (attr->type) {
639
0
  case CKA_NSS_TRUST_DIGITAL_SIGNATURE:
640
0
  case CKA_NSS_TRUST_NON_REPUDIATION:
641
0
  case CKA_NSS_TRUST_KEY_ENCIPHERMENT:
642
0
  case CKA_NSS_TRUST_DATA_ENCIPHERMENT:
643
0
  case CKA_NSS_TRUST_KEY_AGREEMENT:
644
0
  case CKA_NSS_TRUST_KEY_CERT_SIGN:
645
0
  case CKA_NSS_TRUST_CRL_SIGN:
646
0
  case CKA_NSS_TRUST_SERVER_AUTH:
647
0
  case CKA_NSS_TRUST_CLIENT_AUTH:
648
0
  case CKA_NSS_TRUST_CODE_SIGNING:
649
0
  case CKA_NSS_TRUST_EMAIL_PROTECTION:
650
0
  case CKA_NSS_TRUST_IPSEC_END_SYSTEM:
651
0
  case CKA_NSS_TRUST_IPSEC_TUNNEL:
652
0
  case CKA_NSS_TRUST_IPSEC_USER:
653
0
  case CKA_NSS_TRUST_TIME_STAMPING:
654
0
  case CKA_TRUST_SERVER_AUTH:
655
0
  case CKA_TRUST_CLIENT_AUTH:
656
0
  case CKA_TRUST_CODE_SIGNING:
657
0
  case CKA_TRUST_EMAIL_PROTECTION:
658
0
  case CKA_TRUST_IPSEC_IKE:
659
0
  case CKA_TRUST_TIME_STAMPING:
660
0
  case CKA_TRUST_OCSP_SIGNING:
661
0
    break;
662
0
  default:
663
0
    return false;
664
0
  }
665
666
0
  return attribute_is_ulong_of_type (attr, attr->type);
667
0
}
668
669
static bool
670
attribute_is_sensitive (const CK_ATTRIBUTE *attr,
671
                        CK_OBJECT_CLASS klass)
672
0
{
673
  /*
674
   * Don't print any just attribute, since they may contain
675
   * sensitive data
676
   */
677
678
0
  switch (attr->type) {
679
0
  #define X(x) case x: return false;
680
0
  X (CKA_CLASS)
681
0
  X (CKA_TOKEN)
682
0
  X (CKA_PRIVATE)
683
0
  X (CKA_LABEL)
684
0
  X (CKA_APPLICATION)
685
0
  X (CKA_OBJECT_ID)
686
0
  X (CKA_CERTIFICATE_TYPE)
687
0
  X (CKA_ISSUER)
688
0
  X (CKA_SERIAL_NUMBER)
689
0
  X (CKA_AC_ISSUER)
690
0
  X (CKA_OWNER)
691
0
  X (CKA_ATTR_TYPES)
692
0
  X (CKA_TRUSTED)
693
0
  X (CKA_CERTIFICATE_CATEGORY)
694
0
  X (CKA_JAVA_MIDP_SECURITY_DOMAIN)
695
0
  X (CKA_URL)
696
0
  X (CKA_HASH_OF_SUBJECT_PUBLIC_KEY)
697
0
  X (CKA_HASH_OF_ISSUER_PUBLIC_KEY)
698
0
  X (CKA_CHECK_VALUE)
699
0
  X (CKA_KEY_TYPE)
700
0
  X (CKA_SUBJECT)
701
0
  X (CKA_ID)
702
0
  X (CKA_SENSITIVE)
703
0
  X (CKA_ENCRYPT)
704
0
  X (CKA_DECRYPT)
705
0
  X (CKA_WRAP)
706
0
  X (CKA_UNWRAP)
707
0
  X (CKA_SIGN)
708
0
  X (CKA_SIGN_RECOVER)
709
0
  X (CKA_VERIFY)
710
0
  X (CKA_VERIFY_RECOVER)
711
0
  X (CKA_DERIVE)
712
0
  X (CKA_START_DATE)
713
0
  X (CKA_END_DATE)
714
0
  X (CKA_MODULUS_BITS)
715
0
  X (CKA_PRIME_BITS)
716
  /* X (CKA_SUBPRIME_BITS) */
717
  /* X (CKA_SUB_PRIME_BITS) */
718
0
  X (CKA_VALUE_BITS)
719
0
  X (CKA_VALUE_LEN)
720
0
  X (CKA_EXTRACTABLE)
721
0
  X (CKA_LOCAL)
722
0
  X (CKA_NEVER_EXTRACTABLE)
723
0
  X (CKA_ALWAYS_SENSITIVE)
724
0
  X (CKA_KEY_GEN_MECHANISM)
725
0
  X (CKA_MODIFIABLE)
726
0
  X (CKA_SECONDARY_AUTH)
727
0
  X (CKA_AUTH_PIN_FLAGS)
728
0
  X (CKA_ALWAYS_AUTHENTICATE)
729
0
  X (CKA_WRAP_WITH_TRUSTED)
730
0
  X (CKA_WRAP_TEMPLATE)
731
0
  X (CKA_UNWRAP_TEMPLATE)
732
0
  X (CKA_HW_FEATURE_TYPE)
733
0
  X (CKA_RESET_ON_INIT)
734
0
  X (CKA_HAS_RESET)
735
0
  X (CKA_PIXEL_X)
736
0
  X (CKA_PIXEL_Y)
737
0
  X (CKA_RESOLUTION)
738
0
  X (CKA_CHAR_ROWS)
739
0
  X (CKA_CHAR_COLUMNS)
740
0
  X (CKA_COLOR)
741
0
  X (CKA_BITS_PER_PIXEL)
742
0
  X (CKA_CHAR_SETS)
743
0
  X (CKA_ENCODING_METHODS)
744
0
  X (CKA_MIME_TYPES)
745
0
  X (CKA_MECHANISM_TYPE)
746
0
  X (CKA_REQUIRED_CMS_ATTRIBUTES)
747
0
  X (CKA_DEFAULT_CMS_ATTRIBUTES)
748
0
  X (CKA_SUPPORTED_CMS_ATTRIBUTES)
749
0
  X (CKA_ALLOWED_MECHANISMS)
750
0
  X (CKA_TRUST_SERVER_AUTH)
751
0
  X (CKA_TRUST_CLIENT_AUTH)
752
0
  X (CKA_TRUST_CODE_SIGNING)
753
0
  X (CKA_TRUST_EMAIL_PROTECTION)
754
0
  X (CKA_TRUST_IPSEC_IKE)
755
0
  X (CKA_TRUST_TIME_STAMPING)
756
0
  X (CKA_TRUST_OCSP_SIGNING)
757
0
  X (CKA_X_ASSERTION_TYPE)
758
0
  X (CKA_X_CERTIFICATE_VALUE)
759
0
  X (CKA_X_PURPOSE)
760
0
  X (CKA_X_PEER)
761
0
  X (CKA_X_DISTRUSTED)
762
0
  X (CKA_X_CRITICAL)
763
0
  X (CKA_PUBLIC_KEY_INFO)
764
0
  X (CKA_NSS_URL)
765
0
  X (CKA_NSS_EMAIL)
766
0
  X (CKA_NSS_SMIME_INFO)
767
0
  X (CKA_NSS_SMIME_TIMESTAMP)
768
0
  X (CKA_NSS_PKCS8_SALT)
769
0
  X (CKA_NSS_PASSWORD_CHECK)
770
0
  X (CKA_NSS_EXPIRES)
771
0
  X (CKA_NSS_KRL)
772
0
  X (CKA_NSS_PQG_COUNTER)
773
0
  X (CKA_NSS_PQG_SEED)
774
0
  X (CKA_NSS_PQG_H)
775
0
  X (CKA_NSS_PQG_SEED_BITS)
776
0
  X (CKA_NSS_MODULE_SPEC)
777
0
  X (CKA_NSS_TRUST_DIGITAL_SIGNATURE)
778
0
  X (CKA_NSS_TRUST_NON_REPUDIATION)
779
0
  X (CKA_NSS_TRUST_KEY_ENCIPHERMENT)
780
0
  X (CKA_NSS_TRUST_DATA_ENCIPHERMENT)
781
0
  X (CKA_NSS_TRUST_KEY_AGREEMENT)
782
0
  X (CKA_NSS_TRUST_KEY_CERT_SIGN)
783
0
  X (CKA_NSS_TRUST_CRL_SIGN)
784
0
  X (CKA_NSS_TRUST_SERVER_AUTH)
785
0
  X (CKA_NSS_TRUST_CLIENT_AUTH)
786
0
  X (CKA_NSS_TRUST_CODE_SIGNING)
787
0
  X (CKA_NSS_TRUST_EMAIL_PROTECTION)
788
0
  X (CKA_NSS_TRUST_IPSEC_END_SYSTEM)
789
0
  X (CKA_NSS_TRUST_IPSEC_TUNNEL)
790
0
  X (CKA_NSS_TRUST_IPSEC_USER)
791
0
  X (CKA_NSS_TRUST_TIME_STAMPING)
792
0
  X (CKA_NSS_TRUST_STEP_UP_APPROVED)
793
0
  X (CKA_NSS_CERT_SHA1_HASH)
794
0
  X (CKA_NSS_CERT_MD5_HASH)
795
0
  X (CKA_IBM_OPAQUE)
796
0
  X (CKA_IBM_RESTRICTABLE)
797
0
  X (CKA_IBM_NEVER_MODIFIABLE)
798
0
  X (CKA_IBM_RETAINKEY)
799
0
  X (CKA_IBM_ATTRBOUND)
800
0
  X (CKA_IBM_KEYTYPE)
801
0
  X (CKA_IBM_CV)
802
0
  X (CKA_IBM_MACKEY)
803
0
  X (CKA_IBM_USE_AS_DATA)
804
0
  X (CKA_IBM_STRUCT_PARAMS)
805
0
  X (CKA_IBM_STD_COMPLIANCE1)
806
0
  X (CKA_IBM_PROTKEY_EXTRACTABLE)
807
0
  X (CKA_IBM_PROTKEY_NEVER_EXTRACTABLE)
808
0
  X (CKA_IBM_OPAQUE_PKEY)
809
0
  X (CKA_IBM_DILITHIUM_MODE)
810
0
  X (CKA_IBM_DILITHIUM_KEYFORM)
811
0
  X (CKA_IBM_DILITHIUM_RHO)
812
0
  X (CKA_IBM_DILITHIUM_T1)
813
0
  X (CKA_IBM_KYBER_MODE)
814
0
  X (CKA_IBM_KYBER_PK)
815
0
  X (CKA_IBM_KYBER_KEYFORM)
816
0
  case CKA_VALUE:
817
0
    return (klass != CKO_CERTIFICATE &&
818
0
      klass != CKO_X_CERTIFICATE_EXTENSION);
819
0
  #undef X
820
0
  }
821
822
0
  return true;
823
0
}
824
825
static void
826
format_class (p11_buffer *buffer,
827
              CK_OBJECT_CLASS klass)
828
0
{
829
0
  const char *string = p11_constant_name (p11_constant_classes, klass);
830
0
  if (string != NULL)
831
0
    p11_buffer_add (buffer, string, -1);
832
0
  else
833
0
    buffer_append_printf (buffer, "0x%08lX", klass);
834
0
}
835
836
static void
837
format_assertion_type (p11_buffer *buffer,
838
                       CK_X_ASSERTION_TYPE type)
839
0
{
840
0
  const char *string = p11_constant_name (p11_constant_asserts, type);
841
0
  if (string != NULL)
842
0
    p11_buffer_add (buffer, string, -1);
843
0
  else
844
0
    buffer_append_printf (buffer, "0x%08lX", type);
845
0
}
846
847
static void
848
format_key_type (p11_buffer *buffer,
849
                 CK_KEY_TYPE type)
850
0
{
851
0
  const char *string = p11_constant_name (p11_constant_keys, type);
852
0
  if (string != NULL)
853
0
    p11_buffer_add (buffer, string, -1);
854
0
  else
855
0
    buffer_append_printf (buffer, "0x%08lX", type);
856
0
}
857
858
static void
859
format_certificate_type (p11_buffer *buffer,
860
                         CK_CERTIFICATE_TYPE type)
861
0
{
862
0
  const char *string = p11_constant_name (p11_constant_certs, type);
863
0
  if (string != NULL)
864
0
    p11_buffer_add (buffer, string, -1);
865
0
  else
866
0
    buffer_append_printf (buffer, "0x%08lX", type);
867
0
}
868
869
static void
870
format_trust_value (p11_buffer *buffer,
871
                    CK_TRUST trust)
872
0
{
873
0
  const char *string = p11_constant_name (p11_constant_trusts, trust);
874
0
  if (string != NULL)
875
0
    p11_buffer_add (buffer, string, -1);
876
0
  else
877
0
    buffer_append_printf (buffer, "0x%08lX", trust);
878
0
}
879
880
static void
881
format_certificate_category (p11_buffer *buffer,
882
                             CK_ULONG category)
883
0
{
884
0
  const char *string = p11_constant_name (p11_constant_categories, category);
885
0
  if (string != NULL)
886
0
    buffer_append_printf (buffer, "%lu (%s)", category, string);
887
0
  else
888
0
    buffer_append_printf (buffer, "%lu", category);
889
0
}
890
891
static void
892
format_attribute_type (p11_buffer *buffer,
893
                       CK_ULONG type)
894
0
{
895
0
  const char *string = p11_constant_name (p11_constant_types, type);
896
0
  if (string != NULL)
897
0
    p11_buffer_add (buffer, string, -1);
898
0
  else
899
0
    buffer_append_printf (buffer, "CKA_0x%08lX", type);
900
0
}
901
902
static void
903
format_some_bytes (p11_buffer *buffer,
904
                   void *bytes,
905
                   CK_ULONG length)
906
0
{
907
0
  unsigned char ch;
908
0
  const unsigned char *data = bytes;
909
0
  CK_ULONG i;
910
911
0
  if (bytes == NULL) {
912
0
    p11_buffer_add (buffer, "NULL", -1);
913
0
    return;
914
0
  }
915
916
0
  p11_buffer_add (buffer, "\"", 1);
917
0
  for (i = 0; i < length && i < 128; i++) {
918
0
    ch = data[i];
919
0
    if (ch == '\t')
920
0
      p11_buffer_add (buffer, "\\t", -1);
921
0
    else if (ch == '\n')
922
0
      p11_buffer_add (buffer, "\\n", -1);
923
0
    else if (ch == '\r')
924
0
      p11_buffer_add (buffer, "\\r", -1);
925
0
    else if (ch >= 32 && ch < 127)
926
0
      p11_buffer_add (buffer, &ch, 1);
927
0
    else
928
0
      buffer_append_printf (buffer, "\\x%02x", ch);
929
0
  }
930
931
0
  if (i < length)
932
0
    buffer_append_printf (buffer, "...");
933
0
  p11_buffer_add (buffer, "\"", 1);
934
0
}
935
936
void
937
p11_attr_format (p11_buffer *buffer,
938
                 const CK_ATTRIBUTE *attr,
939
                 CK_OBJECT_CLASS klass)
940
0
{
941
0
  p11_buffer_add (buffer, "{ ", -1);
942
0
  format_attribute_type (buffer, attr->type);
943
0
  p11_buffer_add (buffer, " = ", -1);
944
0
  if (attr->ulValueLen == CKA_INVALID) {
945
0
    buffer_append_printf (buffer, "(-1) INVALID");
946
0
  } else if (attribute_is_ulong_of_type (attr, CKA_CLASS)) {
947
0
    format_class (buffer, *((CK_OBJECT_CLASS *)attr->pValue));
948
0
  } else if (attribute_is_ulong_of_type (attr, CKA_X_ASSERTION_TYPE)) {
949
0
    format_assertion_type (buffer, *((CK_X_ASSERTION_TYPE *)attr->pValue));
950
0
  } else if (attribute_is_ulong_of_type (attr, CKA_CERTIFICATE_TYPE)) {
951
0
    format_certificate_type (buffer, *((CK_CERTIFICATE_TYPE *)attr->pValue));
952
0
  } else if (attribute_is_ulong_of_type (attr, CKA_CERTIFICATE_CATEGORY)) {
953
0
    format_certificate_category (buffer, *((CK_ULONG *)attr->pValue));
954
0
  } else if (attribute_is_ulong_of_type (attr, CKA_KEY_TYPE)) {
955
0
    format_key_type (buffer, *((CK_KEY_TYPE *)attr->pValue));
956
0
  } else if (attribute_is_trust_value (attr)) {
957
0
    format_trust_value (buffer, *((CK_TRUST *)attr->pValue));
958
0
  } else if (attribute_is_sensitive (attr, klass)) {
959
0
    buffer_append_printf (buffer, "(%lu) NOT-PRINTED", attr->ulValueLen);
960
0
  } else {
961
0
    buffer_append_printf (buffer, "(%lu) ", attr->ulValueLen);
962
0
    format_some_bytes (buffer, attr->pValue, attr->ulValueLen);
963
0
  }
964
0
  p11_buffer_add (buffer, " }", -1);
965
0
}
966
967
void
968
p11_attrs_format (p11_buffer *buffer,
969
                  const CK_ATTRIBUTE *attrs,
970
                  int count)
971
0
{
972
0
  CK_BBOOL first = CK_TRUE;
973
0
  CK_OBJECT_CLASS klass;
974
0
  int i;
975
976
0
  if (count < 0)
977
0
    count = p11_attrs_count (attrs);
978
979
0
  if (!p11_attrs_findn_ulong (attrs, CKA_CLASS, count, &klass))
980
0
    klass = CKA_INVALID;
981
982
0
  buffer_append_printf (buffer, "(%d) [", count);
983
0
  for (i = 0; i < count; i++) {
984
0
    if (first)
985
0
      p11_buffer_add (buffer, " ", 1);
986
0
    else
987
0
      p11_buffer_add (buffer, ", ", 2);
988
0
    first = CK_FALSE;
989
0
    p11_attr_format (buffer, attrs + i, klass);
990
0
  }
991
0
  p11_buffer_add (buffer, " ]", -1);
992
0
}
993
994
char *
995
p11_attrs_to_string (const CK_ATTRIBUTE *attrs,
996
                     int count)
997
0
{
998
0
  p11_buffer buffer;
999
0
  if (!p11_buffer_init_null (&buffer, 128))
1000
0
    return_val_if_reached (NULL);
1001
0
  p11_attrs_format (&buffer, attrs, count);
1002
0
  return p11_buffer_steal (&buffer, NULL);
1003
0
}
1004
1005
char *
1006
p11_attr_to_string (const CK_ATTRIBUTE *attr,
1007
                    CK_OBJECT_CLASS klass)
1008
0
{
1009
0
  p11_buffer buffer;
1010
0
  if (!p11_buffer_init_null (&buffer, 32))
1011
0
    return_val_if_reached (NULL);
1012
0
  p11_attr_format (&buffer, attr, klass);
1013
  return p11_buffer_steal (&buffer, NULL);
1014
0
}