1 /*
2 * Copyright (C) 2015 Red Hat, Inc.
3 *
4 * Author: Nikos Mavrogiannopoulos
5 *
6 * This file is part of GnuTLS.
7 *
8 * The GnuTLS is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 2.1 of
11 * the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>
20 *
21 */
22
23 /* Functions that relate on PKCS7 attribute setting.
24 */
25
26 #include "gnutls_int.h"
27
28 #include <datum.h>
29 #include <global.h>
30 #include "errors.h"
31 #include <common.h>
32 #include <x509_b64.h>
33 #include <gnutls/abstract.h>
34 #include <gnutls/pkcs7.h>
35
36 /**
37 * gnutls_pkcs7_add_attr:
38 * @list: A list of existing attributes or pointer to %NULL for the first one
39 * @oid: the OID of the attribute to be set
40 * @data: the raw (DER-encoded) data of the attribute to be set
41 * @flags: zero or %GNUTLS_PKCS7_ATTR_ENCODE_OCTET_STRING
42 *
43 * This function will set a PKCS #7 attribute in the provided list.
44 * If this function fails, the previous list would be deallocated.
45 *
46 * Note that any attributes set with this function must either be
47 * DER or BER encoded, unless a special flag is present.
48 *
49 * Returns: On success, the new list head, otherwise %NULL.
50 *
51 * Since: 3.4.2
52 **/
53 int
gnutls_pkcs7_add_attr(gnutls_pkcs7_attrs_t * list,const char * oid,gnutls_datum_t * data,unsigned flags)54 gnutls_pkcs7_add_attr(gnutls_pkcs7_attrs_t * list, const char *oid,
55 gnutls_datum_t * data, unsigned flags)
56 {
57 int ret;
58 gnutls_pkcs7_attrs_st *r;
59
60 r = gnutls_calloc(1, sizeof(gnutls_pkcs7_attrs_st));
61 if (r == NULL)
62 goto fail;
63
64 if (flags & GNUTLS_PKCS7_ATTR_ENCODE_OCTET_STRING) {
65 ret = _gnutls_x509_encode_string(ASN1_ETYPE_OCTET_STRING,
66 data->data, data->size,
67 &r->data);
68 } else {
69 ret = _gnutls_set_datum(&r->data, data->data, data->size);
70 }
71 if (ret < 0)
72 goto fail;
73
74 r->oid = gnutls_strdup(oid);
75 if (r->oid == NULL)
76 goto fail;
77
78 r->next = *list;
79 *list = r;
80
81 return 0;
82 fail:
83 if (r) {
84 gnutls_free(r->data.data);
85 gnutls_free(r);
86 }
87 gnutls_pkcs7_attrs_deinit(*list);
88 return GNUTLS_E_MEMORY_ERROR;
89
90 }
91
92 /**
93 * gnutls_pkcs7_get_attr:
94 * @list: A list of existing attributes or %NULL for the first one
95 * @idx: the index of the attribute to get
96 * @oid: the OID of the attribute (read-only)
97 * @data: the raw data of the attribute
98 * @flags: zero or %GNUTLS_PKCS7_ATTR_ENCODE_OCTET_STRING
99 *
100 * This function will get a PKCS #7 attribute from the provided list.
101 * The OID is a constant string, but data will be allocated and must be
102 * deinitialized by the caller.
103 *
104 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
105 * negative error value. %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned
106 * if there are no data in the current index.
107 *
108 * Since: 3.4.2
109 **/
110 int
gnutls_pkcs7_get_attr(gnutls_pkcs7_attrs_t list,unsigned idx,char ** oid,gnutls_datum_t * data,unsigned flags)111 gnutls_pkcs7_get_attr(gnutls_pkcs7_attrs_t list, unsigned idx, char **oid,
112 gnutls_datum_t * data, unsigned flags)
113 {
114 unsigned i;
115 gnutls_pkcs7_attrs_st *p = list;
116 int ret;
117
118 for (i = 0; i < idx; i++) {
119 p = p->next;
120 if (p == NULL)
121 break;
122 }
123
124 if (p == NULL)
125 return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
126
127 *oid = p->oid;
128
129 if (flags & GNUTLS_PKCS7_ATTR_ENCODE_OCTET_STRING) {
130 ret = _gnutls_x509_decode_string(ASN1_ETYPE_OCTET_STRING,
131 p->data.data, p->data.size,
132 data, 1);
133 } else {
134 ret = _gnutls_set_datum(data, p->data.data, p->data.size);
135 }
136 if (ret < 0)
137 return gnutls_assert_val(ret);
138
139 return 0;
140 }
141
142 /**
143 * gnutls_pkcs7_attrs_deinit:
144 * @list: A list of existing attributes
145 *
146 * This function will clear a PKCS #7 attribute list.
147 *
148 * Since: 3.4.2
149 **/
gnutls_pkcs7_attrs_deinit(gnutls_pkcs7_attrs_t list)150 void gnutls_pkcs7_attrs_deinit(gnutls_pkcs7_attrs_t list)
151 {
152 gnutls_pkcs7_attrs_st *r = list, *next;
153
154 while (r) {
155 next = r->next;
156
157 gnutls_free(r->data.data);
158 gnutls_free(r->oid);
159 gnutls_free(r);
160 r = next;
161 }
162 }
163