27
[QCRYPTO_HASH_ALGO_RIPEMD160] = GNUTLS_DIG_RMD160,
28
};
29
30
+static const int qcrypto_to_gnutls_keyid_flags_map[] = {
31
+ [QCRYPTO_HASH_ALGO_MD5] = -1,
32
+ [QCRYPTO_HASH_ALGO_SHA1] = GNUTLS_KEYID_USE_SHA1,
33
+ [QCRYPTO_HASH_ALGO_SHA224] = -1,
34
+ [QCRYPTO_HASH_ALGO_SHA256] = GNUTLS_KEYID_USE_SHA256,
35
+ [QCRYPTO_HASH_ALGO_SHA384] = -1,
36
+ [QCRYPTO_HASH_ALGO_SHA512] = GNUTLS_KEYID_USE_SHA512,
37
+ [QCRYPTO_HASH_ALGO_RIPEMD160] = -1,
38
+};
39
+
40
int qcrypto_get_x509_cert_fingerprint(uint8_t *cert, size_t size,
41
QCryptoHashAlgo alg,
42
uint8_t *result,
132
return ret;
133
}
134
135
+int qcrypto_x509_check_cert_times(uint8_t *cert, size_t size, Error **errp)
136
+{
137
+ int rc;
138
+ int ret = -1;
139
+ gnutls_x509_crt_t crt;
140
+ gnutls_datum_t datum = {.data = cert, .size = size};
141
+ time_t now = time(NULL);
142
+ time_t exp_time;
143
+ time_t act_time;
144
+
145
+ if (now == ((time_t)-1)) {
146
+ error_setg_errno(errp, errno, "Cannot get current time");
147
+ return ret;
148
+ }
149
+
150
+ rc = gnutls_x509_crt_init(&crt);
151
+ if (rc < 0) {
152
+ error_setg(errp, "Failed to initialize certificate: %s", gnutls_strerror(rc));
153
+ return ret;
154
+ }
155
+
156
+ rc = gnutls_x509_crt_import(crt, &datum, GNUTLS_X509_FMT_PEM);
157
+ if (rc != 0) {
158
+ error_setg(errp, "Failed to import certificate: %s", gnutls_strerror(rc));
159
+ goto cleanup;
160
+ }
161
+
162
+ exp_time = gnutls_x509_crt_get_expiration_time(crt);
163
+ if (exp_time == ((time_t)-1)) {
164
+ error_setg(errp, "Failed to get certificate expiration time");
165
+ goto cleanup;
166
+ }
167
+ if (exp_time < now) {
168
+ error_setg(errp, "The certificate has expired");
169
+ goto cleanup;
170
+ }
171
+
172
+ act_time = gnutls_x509_crt_get_activation_time(crt);
173
+ if (act_time == ((time_t)-1)) {
174
+ error_setg(errp, "Failed to get certificate activation time");
175
+ goto cleanup;
176
+ }
177
+ if (act_time > now) {
178
+ error_setg(errp, "The certificate is not yet active");
179
+ goto cleanup;
180
+ }
181
+
182
+ ret = 0;
183
+
184
+cleanup:
185
+ gnutls_x509_crt_deinit(crt);
186
+ return ret;
187
+}
188
+
189
+static int qcrypto_x509_get_pk_algorithm(uint8_t *cert, size_t size, Error **errp)
190
+{
191
+ int rc;
192
+ int ret = -1;
193
+ unsigned int bits;
194
+ gnutls_x509_crt_t crt;
195
+ gnutls_datum_t datum = {.data = cert, .size = size};
196
+
197
+ rc = gnutls_x509_crt_init(&crt);
198
+ if (rc < 0) {
199
+ error_setg(errp, "Failed to initialize certificate: %s", gnutls_strerror(rc));
200
+ return ret;
201
+ }
202
+
203
+ rc = gnutls_x509_crt_import(crt, &datum, GNUTLS_X509_FMT_PEM);
204
+ if (rc != 0) {
205
+ error_setg(errp, "Failed to import certificate: %s", gnutls_strerror(rc));
206
+ goto cleanup;
207
+ }
208
+
209
+ rc = gnutls_x509_crt_get_pk_algorithm(crt, &bits);
210
+ if (rc < 0) {
211
+ error_setg(errp, "Unknown public key algorithm %d", rc);
212
+ goto cleanup;
213
+ }
214
+
215
+ ret = rc;
216
+
217
+cleanup:
218
+ gnutls_x509_crt_deinit(crt);
219
+ return ret;
220
+}
221
+
222
+int qcrypto_x509_get_cert_key_id(uint8_t *cert, size_t size,
223
+ QCryptoHashAlgo hash_alg,
224
+ uint8_t **result,
225
+ size_t *resultlen,
226
+ Error **errp)
227
+{
228
+ int rc;
229
+ int ret = -1;
230
+ gnutls_x509_crt_t crt;
231
+ gnutls_datum_t datum = {.data = cert, .size = size};
232
+
233
+ if (hash_alg >= G_N_ELEMENTS(qcrypto_to_gnutls_hash_alg_map)) {
234
+ error_setg(errp, "Unknown hash algorithm %d", hash_alg);
235
+ return ret;
236
+ }
237
+
238
+ if (hash_alg >= G_N_ELEMENTS(qcrypto_to_gnutls_keyid_flags_map) ||
239
+ qcrypto_to_gnutls_keyid_flags_map[hash_alg] == -1) {
240
+ error_setg(errp, "Unsupported key id flag %d", hash_alg);
241
+ return ret;
242
+ }
243
+
244
+ rc = gnutls_x509_crt_init(&crt);
245
+ if (rc < 0) {
246
+ error_setg(errp, "Failed to initialize certificate: %s", gnutls_strerror(rc));
247
+ return ret;
248
+ }
249
+
250
+ rc = gnutls_x509_crt_import(crt, &datum, GNUTLS_X509_FMT_PEM);
251
+ if (rc != 0) {
252
+ error_setg(errp, "Failed to import certificate: %s", gnutls_strerror(rc));
253
+ goto cleanup;
254
+ }
255
+
256
+ *resultlen = gnutls_hash_get_len(qcrypto_to_gnutls_hash_alg_map[hash_alg]);
257
+ if (*resultlen == 0) {
258
+ error_setg(errp, "Failed to get hash algorithm length: %s", gnutls_strerror(rc));
259
+ goto cleanup;
260
+ }
261
+
262
+ *result = g_malloc0(*resultlen);
263
+ if (gnutls_x509_crt_get_key_id(crt,
264
+ qcrypto_to_gnutls_keyid_flags_map[hash_alg],
265
+ *result, resultlen) != 0) {
266
+ error_setg(errp, "Failed to get key ID from certificate");
267
+ g_clear_pointer(result, g_free);
268
+ goto cleanup;
269
+ }
270
+
271
+ ret = 0;
272
+
273
+cleanup:
274
+ gnutls_x509_crt_deinit(crt);
275
+ return ret;
276
+}
277
+
278
+static int qcrypto_x509_get_ecc_curve(uint8_t *cert, size_t size, Error **errp)
279
+{
280
+ int rc;
281
+ int ret = -1;
282
+ gnutls_x509_crt_t crt;
283
+ gnutls_datum_t datum = {.data = cert, .size = size};
284
+ gnutls_ecc_curve_t curve_id;
285
+ gnutls_datum_t x = {.data = NULL, .size = 0};
286
+ gnutls_datum_t y = {.data = NULL, .size = 0};
287
+
288
+ rc = gnutls_x509_crt_init(&crt);
289
+ if (rc < 0) {
290
+ error_setg(errp, "Failed to initialize certificate: %s", gnutls_strerror(rc));
291
+ return ret;
292
+ }
293
+
294
+ rc = gnutls_x509_crt_import(crt, &datum, GNUTLS_X509_FMT_PEM);
295
+ if (rc != 0) {
296
+ error_setg(errp, "Failed to import certificate: %s", gnutls_strerror(rc));
297
+ goto cleanup;
298
+ }
299
+
300
+ rc = gnutls_x509_crt_get_pk_ecc_raw(crt, &curve_id, &x, &y);
301
+ if (rc != 0) {
302
+ error_setg(errp, "Failed to get ECC public key curve: %s", gnutls_strerror(rc));
303
+ goto cleanup;
304
+ }
305
+
306
+ ret = curve_id;
307
+
308
+cleanup:
309
+ gnutls_x509_crt_deinit(crt);
310
+ g_free(x.data);
311
+ g_free(y.data);
312
+ return ret;
313
+}
314
+
315
+int qcrypto_x509_check_ecc_curve_p521(uint8_t *cert, size_t size, Error **errp)
316
+{
317
+ int algo;
318
+ int curve_id;
319
+
320
+ algo = qcrypto_x509_get_pk_algorithm(cert, size, errp);
321
+ if (algo != GNUTLS_PK_ECDSA) {
322
+ return 0;
323
+ }
324
+
325
+ curve_id = qcrypto_x509_get_ecc_curve(cert, size, errp);
326
+ if (curve_id == -1) {
327
+ error_setg(errp, "Failed to get ECC curve");
328
+ return -1;
329
+ }
330
+
331
+ if (curve_id == GNUTLS_ECC_CURVE_INVALID) {
332
+ error_setg(errp, "Invalid ECC curve");
333
+ return -1;
334
+ }
335
+
336
+ return curve_id == GNUTLS_ECC_CURVE_SECP521R1;
337
+}
338
+
339
#else /* ! CONFIG_GNUTLS */
340
341
int qcrypto_get_x509_cert_fingerprint(uint8_t *cert, size_t size,
357
return -1;
358
}
359
360
+int qcrypto_x509_check_cert_times(uint8_t *cert, size_t size, Error **errp)
361
+{
362
+ error_setg(errp, "GNUTLS is required to get certificate times");
363
+ return -1;
364
+}
365
+
366
+int qcrypto_x509_get_cert_key_id(uint8_t *cert, size_t size,
367
+ QCryptoHashAlgo hash_alg,
368
+ uint8_t **result,
369
+ size_t *resultlen,
370
+ Error **errp)
371
+{
372
+ error_setg(errp, "GNUTLS is required to get key ID");
373
+ return -1;
374
+}
375
+
376
+int qcrypto_x509_check_ecc_curve_p521(uint8_t *cert, size_t size, Error **errp)
377
+{
378
+ error_setg(errp, "GNUTLS is required to determine ecc curve");
379
+ return -1;
380
+}
381
+
382
#endif /* ! CONFIG_GNUTLS */