Coverage Report

Created: 2025-11-16 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gnutls/lib/x509/x509_dn.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2013-2016 Nikos Mavrogiannopoulos
3
 * Copyright (C) 2016 Red Hat, Inc.
4
 *
5
 * This file is part of GnuTLS.
6
 *
7
 * The GnuTLS is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public License
9
 * as published by the Free Software Foundation; either version 2.1 of
10
 * the License, or (at your option) any later version.
11
 *
12
 * This library is distributed in the hope that it will be useful, but
13
 * WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public License
18
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
19
 *
20
 */
21
22
/* This file contains functions to handle X.509 certificate generation.
23
 */
24
25
#include "gnutls_int.h"
26
27
#include "datum.h"
28
#include "global.h"
29
#include "errors.h"
30
#include "common.h"
31
#include "x509.h"
32
#include "x509_b64.h"
33
#include <c-ctype.h>
34
35
typedef int (*set_dn_func)(void *, const char *oid, unsigned int raw_flag,
36
         const void *name, unsigned int name_size);
37
38
static int dn_attr_crt_set(set_dn_func f, void *crt, const gnutls_datum_t *name,
39
         const gnutls_datum_t *val, unsigned is_raw)
40
0
{
41
0
  char _oid[MAX_OID_SIZE];
42
0
  gnutls_datum_t tmp;
43
0
  const char *oid;
44
0
  int ret;
45
0
  unsigned i, j;
46
47
0
  if (name->size == 0 || val->size == 0)
48
0
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
49
50
0
  assert(name->data);
51
52
0
  if (c_isdigit(name->data[0]) != 0) {
53
0
    if (name->size >= sizeof(_oid))
54
0
      return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
55
56
0
    memcpy(_oid, name->data, name->size);
57
0
    _oid[name->size] = 0;
58
59
0
    oid = _oid;
60
61
0
    if (gnutls_x509_dn_oid_known(oid) == 0 && !is_raw) {
62
0
      _gnutls_debug_log("Unknown OID: '%s'\n", oid);
63
0
      return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
64
0
    }
65
0
  } else {
66
0
    oid = _gnutls_ldap_string_to_oid((char *)name->data,
67
0
             name->size);
68
0
  }
69
70
0
  if (oid == NULL) {
71
0
    _gnutls_debug_log("Unknown DN attribute: '%.*s'\n",
72
0
          (int)name->size, name->data);
73
0
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
74
0
  }
75
76
0
  if (is_raw) {
77
0
    gnutls_datum_t hex = { val->data + 1, val->size - 1 };
78
79
0
    ret = gnutls_hex_decode2(&hex, &tmp);
80
0
    if (ret < 0)
81
0
      return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
82
0
  } else {
83
0
    tmp.size = val->size;
84
0
    tmp.data = gnutls_malloc(tmp.size + 1);
85
0
    if (tmp.data == NULL) {
86
0
      return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
87
0
    }
88
89
    /* unescape */
90
0
    for (j = i = 0; i < tmp.size; i++) {
91
0
      if (1 + j != val->size && val->data[j] == '\\') {
92
0
        if (val->data[j + 1] == ',' ||
93
0
            val->data[j + 1] == '#' ||
94
0
            val->data[j + 1] == ' ' ||
95
0
            val->data[j + 1] == '+' ||
96
0
            val->data[j + 1] == '"' ||
97
0
            val->data[j + 1] == '<' ||
98
0
            val->data[j + 1] == '>' ||
99
0
            val->data[j + 1] == ';' ||
100
0
            val->data[j + 1] == '\\' ||
101
0
            val->data[j + 1] == '=') {
102
0
          tmp.data[i] = val->data[j + 1];
103
0
          j += 2;
104
0
          tmp.size--;
105
0
        } else {
106
0
          ret = gnutls_assert_val(
107
0
            GNUTLS_E_PARSING_ERROR);
108
0
          goto fail;
109
0
        }
110
0
      } else {
111
0
        tmp.data[i] = val->data[j++];
112
0
      }
113
0
    }
114
0
    tmp.data[tmp.size] = 0;
115
0
  }
116
117
0
  ret = f(crt, oid, is_raw, tmp.data, tmp.size);
118
0
  if (ret < 0) {
119
0
    gnutls_assert();
120
0
    goto fail;
121
0
  }
122
123
0
  ret = 0;
124
0
fail:
125
0
  gnutls_free(tmp.data);
126
0
  return ret;
127
0
}
128
129
static int read_attr_and_val(const char **ptr, gnutls_datum_t *name,
130
           gnutls_datum_t *val, unsigned *is_raw)
131
0
{
132
0
  const unsigned char *p = (void *)*ptr;
133
134
0
  *is_raw = 0;
135
136
  /* skip any space */
137
0
  while (c_isspace(*p))
138
0
    p++;
139
140
  /* Read the name */
141
0
  name->data = (void *)p;
142
0
  while (*p != '=' && *p != 0 && !c_isspace(*p))
143
0
    p++;
144
145
0
  name->size = p - name->data;
146
147
  /* skip any space */
148
0
  while (c_isspace(*p))
149
0
    p++;
150
151
0
  if (*p != '=')
152
0
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
153
0
  p++;
154
155
0
  while (c_isspace(*p))
156
0
    p++;
157
158
0
  if (*p == '#') {
159
0
    *is_raw = 1;
160
0
  }
161
162
  /* Read value */
163
0
  val->data = (void *)p;
164
0
  while (*p != 0 && (*p != ',' || (*p == ',' && *(p - 1) == '\\')) &&
165
0
         *p != '\n') {
166
0
    p++;
167
0
  }
168
0
  val->size = p - (val->data);
169
0
  *ptr = (void *)p;
170
171
0
  p = val->data;
172
  /* check for unescaped '+' - we do not support them */
173
0
  while (*p != 0) {
174
0
    if (*p == '+' && (*(p - 1) != '\\'))
175
0
      return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
176
0
    p++;
177
0
  }
178
179
  /* remove spaces from the end */
180
0
  while (val->size > 0 && c_isspace(val->data[val->size - 1])) {
181
0
    if (val->size > 2 && val->data[val->size - 2] == '\\')
182
0
      break;
183
0
    val->size--;
184
0
  }
185
186
0
  if (val->size == 0 || name->size == 0)
187
0
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
188
189
0
  return 0;
190
0
}
191
192
typedef struct elem_list_st {
193
  gnutls_datum_t name;
194
  gnutls_datum_t val;
195
  const char *pos;
196
  unsigned is_raw;
197
  struct elem_list_st *next;
198
} elem_list_st;
199
200
static int add_new_elem(elem_list_st **head, const gnutls_datum_t *name,
201
      const gnutls_datum_t *val, const char *pos,
202
      unsigned is_raw)
203
0
{
204
0
  elem_list_st *elem = gnutls_malloc(sizeof(*elem));
205
0
  if (elem == NULL)
206
0
    return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
207
208
0
  memcpy(&elem->name, name, sizeof(*name));
209
0
  memcpy(&elem->val, val, sizeof(*val));
210
0
  elem->pos = pos;
211
0
  elem->is_raw = is_raw;
212
0
  elem->next = *head;
213
0
  *head = elem;
214
215
0
  return 0;
216
0
}
217
218
static int crt_set_dn(set_dn_func f, void *crt, const char *dn,
219
          const char **err)
220
0
{
221
0
  const char *p = dn;
222
0
  int ret;
223
0
  gnutls_datum_t name, val;
224
0
  unsigned is_raw;
225
0
  elem_list_st *list = NULL, *plist, *next;
226
227
0
  if (crt == NULL || dn == NULL)
228
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
229
230
  /* We parse the string and set all elements to a linked list in
231
   * reverse order. That way we can encode in reverse order,
232
   * the way RFC4514 requires. */
233
234
  /* For each element */
235
0
  while (*p != 0 && *p != '\n') {
236
0
    if (err)
237
0
      *err = p;
238
239
0
    is_raw = 0;
240
0
    ret = read_attr_and_val(&p, &name, &val, &is_raw);
241
0
    if (ret < 0) {
242
0
      gnutls_assert();
243
0
      goto fail;
244
0
    }
245
246
    /* skip spaces and look for comma */
247
0
    while (c_isspace(*p))
248
0
      p++;
249
250
0
    ret = add_new_elem(&list, &name, &val, p, is_raw);
251
0
    if (ret < 0) {
252
0
      gnutls_assert();
253
0
      goto fail;
254
0
    }
255
256
0
    if (*p != ',' && *p != 0 && *p != '\n') {
257
0
      ret = gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
258
0
      goto fail;
259
0
    }
260
0
    if (*p == ',')
261
0
      p++;
262
0
  }
263
264
0
  plist = list;
265
0
  while (plist) {
266
0
    if (err)
267
0
      *err = plist->pos;
268
0
    ret = dn_attr_crt_set(f, crt, &plist->name, &plist->val,
269
0
              plist->is_raw);
270
0
    if (ret < 0)
271
0
      goto fail;
272
273
0
    plist = plist->next;
274
0
  }
275
276
0
  ret = 0;
277
0
fail:
278
0
  plist = list;
279
0
  while (plist) {
280
0
    next = plist->next;
281
0
    gnutls_free(plist);
282
0
    plist = next;
283
0
  }
284
0
  return ret;
285
0
}
286
287
/**
288
 * gnutls_x509_crt_set_dn:
289
 * @crt: a certificate of type #gnutls_x509_crt_t
290
 * @dn: a comma separated DN string (RFC4514)
291
 * @err: indicates the error position (if any)
292
 *
293
 * This function will set the DN on the provided certificate.
294
 * The input string should be plain ASCII or UTF-8 encoded. On
295
 * DN parsing error %GNUTLS_E_PARSING_ERROR is returned.
296
 *
297
 * Note that DNs are not expected to hold DNS information, and thus
298
 * no automatic IDNA conversions are attempted when using this function.
299
 * If that is required (e.g., store a domain in CN), process the corresponding
300
 * input with gnutls_idna_map().
301
 *
302
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
303
 *   negative error value.
304
 **/
305
int gnutls_x509_crt_set_dn(gnutls_x509_crt_t crt, const char *dn,
306
         const char **err)
307
0
{
308
0
  return crt_set_dn((set_dn_func)gnutls_x509_crt_set_dn_by_oid, crt, dn,
309
0
        err);
310
0
}
311
312
/**
313
 * gnutls_x509_crt_set_issuer_dn:
314
 * @crt: a certificate of type #gnutls_x509_crt_t
315
 * @dn: a comma separated DN string (RFC4514)
316
 * @err: indicates the error position (if any)
317
 *
318
 * This function will set the DN on the provided certificate.
319
 * The input string should be plain ASCII or UTF-8 encoded. On
320
 * DN parsing error %GNUTLS_E_PARSING_ERROR is returned.
321
 *
322
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
323
 *   negative error value.
324
 **/
325
int gnutls_x509_crt_set_issuer_dn(gnutls_x509_crt_t crt, const char *dn,
326
          const char **err)
327
0
{
328
0
  return crt_set_dn((set_dn_func)gnutls_x509_crt_set_issuer_dn_by_oid,
329
0
        crt, dn, err);
330
0
}
331
332
/**
333
 * gnutls_x509_crq_set_dn:
334
 * @crq: a certificate of type #gnutls_x509_crq_t
335
 * @dn: a comma separated DN string (RFC4514)
336
 * @err: indicates the error position (if any)
337
 *
338
 * This function will set the DN on the provided certificate.
339
 * The input string should be plain ASCII or UTF-8 encoded. On
340
 * DN parsing error %GNUTLS_E_PARSING_ERROR is returned.
341
 *
342
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
343
 *   negative error value.
344
 **/
345
int gnutls_x509_crq_set_dn(gnutls_x509_crq_t crq, const char *dn,
346
         const char **err)
347
0
{
348
0
  return crt_set_dn((set_dn_func)gnutls_x509_crq_set_dn_by_oid, crq, dn,
349
0
        err);
350
0
}
351
352
static int set_dn_by_oid(gnutls_x509_dn_t dn, const char *oid,
353
       unsigned int raw_flag, const void *name,
354
       unsigned name_size)
355
0
{
356
0
  return _gnutls_x509_set_dn_oid(dn->asn, "", oid, raw_flag, name,
357
0
               name_size);
358
0
}
359
360
/**
361
 * gnutls_x509_dn_set_str:
362
 * @dn: a pointer to DN
363
 * @str: a comma separated DN string (RFC4514)
364
 * @err: indicates the error position (if any)
365
 *
366
 * This function will set the DN on the provided DN structure.
367
 * The input string should be plain ASCII or UTF-8 encoded. On
368
 * DN parsing error %GNUTLS_E_PARSING_ERROR is returned.
369
 *
370
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
371
 *   negative error value.
372
 *
373
 * Since: 3.5.3
374
 **/
375
int gnutls_x509_dn_set_str(gnutls_x509_dn_t dn, const char *str,
376
         const char **err)
377
0
{
378
0
  if (dn == NULL) {
379
0
    gnutls_assert();
380
0
    return GNUTLS_E_INVALID_REQUEST;
381
0
  }
382
383
0
  return crt_set_dn((set_dn_func)set_dn_by_oid, dn, str, err);
384
0
}
385
386
/**
387
 * gnutls_x509_dn_init:
388
 * @dn: the object to be initialized
389
 *
390
 * This function initializes a #gnutls_x509_dn_t type.
391
 *
392
 * The object returned must be deallocated using
393
 * gnutls_x509_dn_deinit().
394
 *
395
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
396
 *   negative error value.
397
 *
398
 * Since: 2.4.0
399
 **/
400
int gnutls_x509_dn_init(gnutls_x509_dn_t *dn)
401
0
{
402
0
  int result;
403
404
0
  *dn = gnutls_calloc(1, sizeof(gnutls_x509_dn_st));
405
0
  if (*dn == NULL) {
406
0
    gnutls_assert();
407
0
    return GNUTLS_E_MEMORY_ERROR;
408
0
  }
409
410
0
  if ((result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.Name",
411
0
            &(*dn)->asn)) != ASN1_SUCCESS) {
412
0
    gnutls_assert();
413
0
    gnutls_free(*dn);
414
0
    return _gnutls_asn2err(result);
415
0
  }
416
417
0
  return 0;
418
0
}
419
420
/**
421
 * gnutls_x509_dn_import:
422
 * @dn: the structure that will hold the imported DN
423
 * @data: should contain a DER encoded RDN sequence
424
 *
425
 * This function parses an RDN sequence and stores the result to a
426
 * #gnutls_x509_dn_t type. The data must have been initialized
427
 * with gnutls_x509_dn_init(). You may use gnutls_x509_dn_get_rdn_ava() to
428
 * decode the DN.
429
 *
430
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
431
 *   negative error value.
432
 *
433
 * Since: 2.4.0
434
 **/
435
int gnutls_x509_dn_import(gnutls_x509_dn_t dn, const gnutls_datum_t *data)
436
0
{
437
0
  int result;
438
0
  char err[ASN1_MAX_ERROR_DESCRIPTION_SIZE];
439
440
0
  if (data->data == NULL || data->size == 0)
441
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
442
443
0
  result = _asn1_strict_der_decode(&dn->asn, data->data, data->size, err);
444
0
  if (result != ASN1_SUCCESS) {
445
    /* couldn't decode DER */
446
0
    _gnutls_debug_log("ASN.1 Decoding error: %s\n", err);
447
0
    gnutls_assert();
448
0
    return _gnutls_asn2err(result);
449
0
  }
450
451
0
  return 0;
452
0
}
453
454
/**
455
 * gnutls_x509_dn_deinit:
456
 * @dn: a DN uint8_t object pointer.
457
 *
458
 * This function deallocates the DN object as returned by
459
 * gnutls_x509_dn_import().
460
 *
461
 * Since: 2.4.0
462
 **/
463
void gnutls_x509_dn_deinit(gnutls_x509_dn_t dn)
464
0
{
465
0
  asn1_delete_structure(&dn->asn);
466
0
  gnutls_free(dn);
467
0
}
468
469
/**
470
 * gnutls_x509_dn_export:
471
 * @dn: Holds the uint8_t DN object
472
 * @format: the format of output params. One of PEM or DER.
473
 * @output_data: will contain a DN PEM or DER encoded
474
 * @output_data_size: holds the size of output_data (and will be
475
 *   replaced by the actual size of parameters)
476
 *
477
 * This function will export the DN to DER or PEM format.
478
 *
479
 * If the buffer provided is not long enough to hold the output, then
480
 * *@output_data_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER
481
 * will be returned.
482
 *
483
 * If the structure is PEM encoded, it will have a header
484
 * of "BEGIN NAME".
485
 *
486
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
487
 *   negative error value.
488
 **/
489
int gnutls_x509_dn_export(gnutls_x509_dn_t dn, gnutls_x509_crt_fmt_t format,
490
        void *output_data, size_t *output_data_size)
491
0
{
492
0
  if (dn == NULL) {
493
0
    gnutls_assert();
494
0
    return GNUTLS_E_INVALID_REQUEST;
495
0
  }
496
497
0
  return _gnutls_x509_export_int_named(dn->asn, "rdnSequence", format,
498
0
               "NAME", output_data,
499
0
               output_data_size);
500
0
}
501
502
/**
503
 * gnutls_x509_dn_export2:
504
 * @dn: Holds the uint8_t DN object
505
 * @format: the format of output params. One of PEM or DER.
506
 * @out: will contain a DN PEM or DER encoded
507
 *
508
 * This function will export the DN to DER or PEM format.
509
 *
510
 * The output buffer is allocated using gnutls_malloc().
511
 *
512
 * If the structure is PEM encoded, it will have a header
513
 * of "BEGIN NAME".
514
 *
515
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
516
 *   negative error value.
517
 *
518
 * Since: 3.1.3
519
 **/
520
int gnutls_x509_dn_export2(gnutls_x509_dn_t dn, gnutls_x509_crt_fmt_t format,
521
         gnutls_datum_t *out)
522
0
{
523
0
  if (dn == NULL) {
524
0
    gnutls_assert();
525
0
    return GNUTLS_E_INVALID_REQUEST;
526
0
  }
527
528
0
  return _gnutls_x509_export_int_named2(dn->asn, "rdnSequence", format,
529
0
                "NAME", out);
530
0
}
531
532
/**
533
 * gnutls_x509_dn_get_rdn_ava:
534
 * @dn: a pointer to DN
535
 * @irdn: index of RDN
536
 * @iava: index of AVA.
537
 * @ava: Pointer to structure which will hold output information.
538
 *
539
 * Get pointers to data within the DN. The format of the @ava structure
540
 * is shown below.
541
 *
542
 *  struct gnutls_x509_ava_st {
543
 *    gnutls_datum_t oid;
544
 *    gnutls_datum_t value;
545
 *    unsigned long value_tag;
546
 *  };
547
 *
548
 * The X.509 distinguished name is a sequence of sequences of strings
549
 * and this is what the @irdn and @iava indexes model.
550
 *
551
 * Note that @ava will contain pointers into the @dn structure which
552
 * in turns points to the original certificate. Thus you should not
553
 * modify any data or deallocate any of those.
554
 *
555
 * This is a low-level function that requires the caller to do the
556
 * value conversions when necessary (e.g. from UCS-2).
557
 *
558
 * Returns: Returns 0 on success, or an error code.
559
 **/
560
int gnutls_x509_dn_get_rdn_ava(gnutls_x509_dn_t dn, int irdn, int iava,
561
             gnutls_x509_ava_st *ava)
562
0
{
563
0
  asn1_node rdn, elem;
564
0
  asn1_data_node_st vnode;
565
0
  long len;
566
0
  int lenlen, remlen, ret;
567
0
  char rbuf[MAX_NAME_SIZE];
568
0
  unsigned char cls;
569
0
  const unsigned char *ptr;
570
571
0
  iava++;
572
0
  irdn++; /* 0->1, 1->2 etc */
573
574
0
  snprintf(rbuf, sizeof(rbuf), "rdnSequence.?%d.?%d", irdn, iava);
575
0
  rdn = asn1_find_node(dn->asn, rbuf);
576
0
  if (!rdn) {
577
0
    gnutls_assert();
578
0
    return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND;
579
0
  }
580
581
0
  snprintf(rbuf, sizeof(rbuf), "?%d.type", iava);
582
0
  elem = asn1_find_node(rdn, rbuf);
583
0
  if (!elem) {
584
0
    gnutls_assert();
585
0
    return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND;
586
0
  }
587
588
0
  ret = asn1_read_node_value(elem, &vnode);
589
0
  if (ret != ASN1_SUCCESS) {
590
0
    gnutls_assert();
591
0
    return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND;
592
0
  }
593
594
0
  ava->oid.data = (void *)vnode.value;
595
0
  ava->oid.size = vnode.value_len;
596
597
0
  snprintf(rbuf, sizeof(rbuf), "?%d.value", iava);
598
0
  elem = asn1_find_node(rdn, rbuf);
599
0
  if (!elem) {
600
0
    gnutls_assert();
601
0
    return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND;
602
0
  }
603
604
0
  ret = asn1_read_node_value(elem, &vnode);
605
0
  if (ret != ASN1_SUCCESS) {
606
0
    gnutls_assert();
607
0
    return GNUTLS_E_ASN1_ELEMENT_NOT_FOUND;
608
0
  }
609
  /* The value still has the previous tag's length bytes, plus the
610
   * current value's tag and length bytes. Decode them.
611
   */
612
613
0
  ptr = vnode.value;
614
0
  remlen = vnode.value_len;
615
0
  len = asn1_get_length_der(ptr, remlen, &lenlen);
616
0
  if (len < 0) {
617
0
    gnutls_assert();
618
0
    return GNUTLS_E_ASN1_DER_ERROR;
619
0
  }
620
621
0
  ptr += lenlen;
622
0
  remlen -= lenlen;
623
0
  ret = asn1_get_tag_der(ptr, remlen, &cls, &lenlen, &ava->value_tag);
624
0
  if (ret) {
625
0
    gnutls_assert();
626
0
    return _gnutls_asn2err(ret);
627
0
  }
628
629
0
  ptr += lenlen;
630
0
  remlen -= lenlen;
631
632
0
  {
633
0
    signed long tmp;
634
635
0
    tmp = asn1_get_length_der(ptr, remlen, &lenlen);
636
0
    if (tmp < 0) {
637
0
      gnutls_assert();
638
0
      return GNUTLS_E_ASN1_DER_ERROR;
639
0
    }
640
0
    ava->value.size = tmp;
641
0
  }
642
0
  ava->value.data = (void *)(ptr + lenlen);
643
644
0
  return 0;
645
0
}
646
647
/**
648
 * gnutls_x509_dn_get_str:
649
 * @dn: a pointer to DN
650
 * @str: a datum that will hold the name
651
 *
652
 * This function will allocate buffer and copy the name in the provided DN.
653
 * The name will be in the form "C=xxxx,O=yyyy,CN=zzzz" as
654
 * described in RFC4514. The output string will be ASCII or UTF-8
655
 * encoded, depending on the certificate data.
656
 *
657
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
658
 *   negative error value.
659
 *
660
 * Since: 3.4.2
661
 **/
662
int gnutls_x509_dn_get_str(gnutls_x509_dn_t dn, gnutls_datum_t *str)
663
0
{
664
0
  if (dn == NULL) {
665
0
    gnutls_assert();
666
0
    return GNUTLS_E_INVALID_REQUEST;
667
0
  }
668
669
0
  return _gnutls_x509_get_dn(dn->asn, "rdnSequence", str,
670
0
           GNUTLS_X509_DN_FLAG_COMPAT);
671
0
}
672
673
/**
674
 * gnutls_x509_dn_get_str:
675
 * @dn: a pointer to DN
676
 * @str: a datum that will hold the name
677
 * @flags: zero or %GNUTLS_X509_DN_FLAG_COMPAT
678
 *
679
 * This function will allocate buffer and copy the name in the provided DN.
680
 * The name will be in the form "C=xxxx,O=yyyy,CN=zzzz" as
681
 * described in RFC4514. The output string will be ASCII or UTF-8
682
 * encoded, depending on the certificate data.
683
 *
684
 * When the flag %GNUTLS_X509_DN_FLAG_COMPAT is specified, the output
685
 * format will match the format output by previous to 3.5.6 versions of GnuTLS
686
 * which was not not fully RFC4514-compliant.
687
 *
688
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
689
 *   negative error value.
690
 *
691
 * Since: 3.5.7
692
 **/
693
int gnutls_x509_dn_get_str2(gnutls_x509_dn_t dn, gnutls_datum_t *str,
694
          unsigned flags)
695
0
{
696
0
  if (dn == NULL) {
697
0
    gnutls_assert();
698
0
    return GNUTLS_E_INVALID_REQUEST;
699
0
  }
700
701
0
  return _gnutls_x509_get_dn(dn->asn, "rdnSequence", str, flags);
702
0
}