1 /*
2 * aux-data.c: Auxiliary data help functions
3 *
4 * Copyright (C) 2016 Viktor Tarasov <viktor.tarasov@gmail.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #if HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <assert.h>
28 #include <string.h>
29
30 #include "internal.h"
31 #include "common/compat_strlcat.h"
32
33 #include <libopensc/errors.h>
34 #include <libopensc/types.h>
35 #include <libopensc/log.h>
36 #include <libopensc/aux-data.h>
37
38
39 int
sc_aux_data_allocate(struct sc_context * ctx,struct sc_auxiliary_data ** dst,struct sc_auxiliary_data * src)40 sc_aux_data_allocate(struct sc_context *ctx, struct sc_auxiliary_data **dst, struct sc_auxiliary_data *src)
41 {
42 int rv = SC_ERROR_INTERNAL;
43
44 LOG_FUNC_CALLED(ctx);
45
46 if (!dst)
47 LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Cannot allocate auxiliary data");
48
49 if (*dst == NULL) {
50 *dst = calloc(1, sizeof(struct sc_auxiliary_data));
51 if (*dst == NULL)
52 LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot allocate aux. data");
53 }
54
55 if ((src == NULL) || (src->type == SC_AUX_DATA_TYPE_NO_DATA))
56 LOG_FUNC_RETURN(ctx, SC_SUCCESS);
57
58 switch(src->type) {
59 case SC_AUX_DATA_TYPE_MD_CMAP_RECORD:
60 **dst = *src;
61 rv = SC_SUCCESS;
62 break;
63 default:
64 sc_log(ctx, "Invalid aux-data type %X", src->type);
65 LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unknown aux-data type");
66 }
67
68 LOG_FUNC_RETURN(ctx, rv);
69 }
70
71
72 int
sc_aux_data_set_md_guid(struct sc_context * ctx,struct sc_auxiliary_data * aux_data,char * guid)73 sc_aux_data_set_md_guid(struct sc_context *ctx, struct sc_auxiliary_data *aux_data, char *guid)
74 {
75 struct sc_md_cmap_record *rec;
76 int rv = SC_ERROR_INTERNAL;
77
78 LOG_FUNC_CALLED(ctx);
79 if (!aux_data || !guid || strlen(guid) > SC_MD_MAX_CONTAINER_NAME_LEN)
80 LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Cannot set guid for MD container");
81
82 switch(aux_data->type) {
83 case SC_AUX_DATA_TYPE_NO_DATA:
84 memset(aux_data, 0, sizeof(*aux_data));
85 aux_data->type = SC_AUX_DATA_TYPE_MD_CMAP_RECORD;
86 /* fallthrough */
87 case SC_AUX_DATA_TYPE_MD_CMAP_RECORD:
88 rec = &aux_data->data.cmap_record;
89 memcpy(rec->guid, guid, strlen(guid));
90 rec->guid_len = strlen(guid);
91 sc_log(ctx, "set MD container GUID '%s'", aux_data->data.cmap_record.guid);
92 rv = SC_SUCCESS;
93 break;
94 default:
95 sc_log(ctx, "Invalid aux-data type %X", aux_data->type);
96 LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unknown aux-data type");
97 }
98
99 LOG_FUNC_RETURN(ctx, rv);
100 return rv;
101 }
102
103
104 int
sc_aux_data_set_md_flags(struct sc_context * ctx,struct sc_auxiliary_data * aux_data,unsigned char flags)105 sc_aux_data_set_md_flags(struct sc_context *ctx, struct sc_auxiliary_data *aux_data, unsigned char flags)
106 {
107 int rv = SC_ERROR_INTERNAL;
108
109 LOG_FUNC_CALLED(ctx);
110 if (!aux_data)
111 LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Cannot set flags of MD container");
112
113 switch(aux_data->type) {
114 case SC_AUX_DATA_TYPE_NO_DATA:
115 memset(aux_data, 0, sizeof(*aux_data));
116 aux_data->type = SC_AUX_DATA_TYPE_MD_CMAP_RECORD;
117 /* fallthrough */
118 case SC_AUX_DATA_TYPE_MD_CMAP_RECORD:
119 aux_data->data.cmap_record.flags = flags;
120 sc_log(ctx, "set MD container flags '0x%X'", flags);
121 rv = SC_SUCCESS;
122 break;
123 default:
124 sc_log(ctx, "Invalid aux-data type %X", aux_data->type);
125 LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Unknown aux-data type");
126 }
127
128 LOG_FUNC_RETURN(ctx, rv);
129 }
130
131
132 int
sc_aux_data_get_md_guid(struct sc_context * ctx,struct sc_auxiliary_data * aux_data,unsigned flags,unsigned char * out,size_t * out_size)133 sc_aux_data_get_md_guid(struct sc_context *ctx, struct sc_auxiliary_data *aux_data,
134 unsigned flags, unsigned char *out, size_t *out_size)
135 {
136 struct sc_md_cmap_record *cmap_record = NULL;
137 char guid[SC_MD_MAX_CONTAINER_NAME_LEN + 3];
138
139 LOG_FUNC_CALLED(ctx);
140 if(!aux_data || !out || !out_size)
141 LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
142
143 if (aux_data->type != SC_AUX_DATA_TYPE_MD_CMAP_RECORD)
144 LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
145
146 cmap_record = &aux_data->data.cmap_record;
147
148 /* Ignore silently request of '{}' frame is output buffer is too small */
149 if (!flags && *out_size < strlen((char *)cmap_record->guid) + 2)
150 flags = 1;
151
152 *guid = '\0';
153 if (!flags)
154 strncpy(guid, "{", sizeof guid);
155 strlcat(guid, (char *)cmap_record->guid, sizeof(guid)-1);
156 if (!flags)
157 strlcat(guid, "}", sizeof(guid));
158
159 if (*out_size < strlen(guid)) {
160 sc_log(ctx,
161 "aux-data: buffer too small: out_size:%"SC_FORMAT_LEN_SIZE_T"u < guid-length:%"SC_FORMAT_LEN_SIZE_T"u",
162 *out_size, strlen(guid));
163 LOG_FUNC_RETURN(ctx, SC_ERROR_BUFFER_TOO_SMALL);
164 }
165
166 memset(out, 0, *out_size);
167 memcpy(out, guid, strlen(guid));
168 *out_size = strlen(guid);
169
170 sc_log(ctx, "aux-data: returns guid '%s'", (char *)out);
171 LOG_FUNC_RETURN(ctx, SC_SUCCESS);
172 }
173
174
175 int
sc_aux_data_get_md_flags(struct sc_context * ctx,struct sc_auxiliary_data * aux_data,unsigned char * flags)176 sc_aux_data_get_md_flags(struct sc_context *ctx, struct sc_auxiliary_data *aux_data,
177 unsigned char *flags)
178 {
179 LOG_FUNC_CALLED(ctx);
180 if(!aux_data || !flags)
181 LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
182
183 if (aux_data->type != SC_AUX_DATA_TYPE_MD_CMAP_RECORD)
184 LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
185
186 *flags = aux_data->data.cmap_record.flags;
187
188 sc_log(ctx, "aux-data: returns flags '0x%X'", *flags);
189 LOG_FUNC_RETURN(ctx, SC_SUCCESS);
190 }
191
192
193 void
sc_aux_data_free(struct sc_auxiliary_data ** data)194 sc_aux_data_free(struct sc_auxiliary_data **data)
195 {
196 if (data == NULL || *data == NULL)
197 return;
198
199 switch((*data)->type) {
200 case SC_AUX_DATA_TYPE_MD_CMAP_RECORD:
201 free(*data);
202 break;
203 default:
204 break;
205 }
206
207 *data = NULL;
208 }
209
210