1 /*
2 * Copyright 2014-2022 The GmSSL Project. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the License); you may
5 * not use this file except in compliance with the License.
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 */
9
10
11 #include <stdio.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include <gmssl/oid.h>
15 #include <gmssl/x509_alg.h>
16 #include <gmssl/x509_oid.h>
17 #include <gmssl/x509.h>
18 #include <gmssl/rand.h>
19 #include <gmssl/error.h>
20
21
test_x509_version(void)22 static int test_x509_version(void)
23 {
24
25 int tests[] = {
26 X509_version_v1,
27 X509_version_v2,
28 X509_version_v3,
29 -1,
30 };
31 uint8_t buf[256];
32 uint8_t *p = buf;
33 const uint8_t *cp = buf;
34 size_t len = 0;
35 size_t i;
36
37 format_print(stderr, 0, 0, "Version\n");
38 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) {
39 if (x509_explicit_version_to_der(i, tests[i], &p, &len) < 0) {
40 error_print();
41 return -1;
42 }
43 format_bytes(stderr, 0, 4, "", buf, len);
44 }
45 for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) {
46 int ver;
47 if (x509_explicit_version_from_der(i, &ver, &cp, &len) < 0
48 || asn1_check(ver == tests[i]) != 1) {
49 error_print();
50 return -1;
51 }
52 format_print(stderr, 0, 4, "%s\n", x509_version_name(ver));
53 }
54 (void)asn1_length_is_zero(len);
55 printf("%s() ok\n", __FUNCTION__);
56 return 0;
57 }
58
59
test_x509_validity(void)60 static int test_x509_validity(void)
61 {
62 time_t not_before, not_before_;
63 time_t not_after, not_after_;
64 uint8_t buf[256];
65 uint8_t *p = buf;
66 const uint8_t *cp = buf;
67 size_t len = 0;
68 size_t i;
69
70 time(¬_before);
71
72 format_print(stderr, 0, 0, "Validity\n");
73 if (x509_validity_add_days(¬_after, not_before, 365) != 1
74 || x509_validity_to_der(not_before, not_after, &p, &len) != 1) {
75 error_print();
76 return -1;
77 }
78 format_bytes(stderr, 0, 4, "", buf, len);
79 if (x509_validity_from_der(¬_before_, ¬_after_, &cp, &len) != 1
80 || asn1_check(not_before == not_before_) != 1
81 || asn1_check(not_after == not_after_) != 1
82 || asn1_length_is_zero(len) != 1) {
83 error_print();
84 return 1;
85 }
86 printf("%s() ok\n", __FUNCTION__);
87 return 0;
88 }
89
test_x509_attr_type_and_value(void)90 static int test_x509_attr_type_and_value(void)
91 {
92 int oid;
93 int tag;
94 const uint8_t *d;
95 size_t dlen;
96 uint8_t buf[256];
97 uint8_t *p = buf;
98 const uint8_t *cp = buf;
99 size_t len = 0;
100
101 format_print(stderr, 0, 0, "AttributeTypeAndValue\n");
102 if (x509_attr_type_and_value_to_der(OID_at_locality_name, ASN1_TAG_PrintableString, (uint8_t *)"Haidian", strlen("Haidian"), &p, &len) != 1) {
103 error_print();
104 return -1;
105 }
106 format_bytes(stderr, 0, 4, "", buf, len);
107 if (x509_attr_type_and_value_from_der(&oid, &tag, &d, &dlen, &cp, &len) != 1
108 || asn1_check(oid == OID_at_locality_name) != 1
109 || asn1_check(tag == ASN1_TAG_PrintableString) != 1
110 || asn1_check(dlen == strlen("Haidian")) != 1
111 || asn1_check(memcmp("Haidian", d, dlen) == 0) != 1
112 || asn1_length_is_zero(len) != 1) {
113 error_print();
114 return -1;
115 }
116 format_print(stderr, 0, 4, "%s : %s ", x509_name_type_name(oid), asn1_tag_name(tag));
117 format_string(stderr, 0, 0, "", d, dlen);
118 printf("%s() ok\n", __FUNCTION__);
119 return 0;
120 }
121
test_x509_rdn(void)122 static int test_x509_rdn(void)
123 {
124 int oid;
125 int tag;
126 const uint8_t *d;
127 size_t dlen;
128 const uint8_t *more;
129 size_t morelen;
130 uint8_t buf[256];
131 uint8_t *p = buf;
132 const uint8_t *cp = buf;
133 size_t len = 0;
134
135 format_print(stderr, 0, 0, "RDN\n");
136 if (x509_rdn_to_der(OID_at_locality_name, ASN1_TAG_PrintableString,
137 (uint8_t *)"Haidian", strlen("Haidian"), NULL, 0, &p, &len) != 1) {
138 error_print();
139 return -1;
140 }
141 format_bytes(stderr, 0, 4, "", buf, len);
142 if (x509_rdn_from_der(&oid, &tag, &d, &dlen, &more, &morelen, &cp, &len) != 1
143 || asn1_check(oid == OID_at_locality_name) != 1
144 || asn1_check(tag == ASN1_TAG_PrintableString) != 1
145 || asn1_check(dlen == strlen("Haidian")) != 1
146 || asn1_check(memcmp("Haidian", d, dlen) == 0) != 1
147 || asn1_check(more == NULL) != 1
148 || asn1_check(morelen == 0) != 1
149 || asn1_length_is_zero(len) != 1) {
150 error_print();
151 return -1;
152 }
153 format_print(stderr, 0, 4, "%s : %s ", x509_name_type_name(oid), asn1_tag_name(tag));
154 format_string(stderr, 0, 0, "", d, dlen);
155 printf("%s() ok\n", __FUNCTION__);
156 return 0;
157 }
158
test_x509_name(void)159 static int test_x509_name(void)
160 {
161 int err = 0;
162 uint8_t name[512];
163 size_t namelen = 0;
164 uint8_t buf[1024];
165 const uint8_t *cp = buf;
166 uint8_t *p = buf;
167 size_t len = 0;
168
169 if (x509_name_add_country_name(name, &namelen, sizeof(name), "CN") != 1
170 || format_bytes(stderr, 0, 4, "", name, namelen) > 2
171 || x509_name_add_locality_name(name, &namelen, sizeof(name), ASN1_TAG_PrintableString, (uint8_t *)"Haidian", strlen("Haidian")) != 1
172 || format_bytes(stderr, 0, 4, "", name, namelen) > 2
173 || x509_name_add_state_or_province_name(name, &namelen, sizeof(name), ASN1_TAG_PrintableString, (uint8_t *)"Beijing", strlen("Beijing")) != 1
174 || format_bytes(stderr, 0, 4, "", name, namelen) > 2
175 || x509_name_add_organization_name(name, &namelen, sizeof(name), ASN1_TAG_PrintableString, (uint8_t *)"PKU", strlen("PKU")) != 1
176 || format_bytes(stderr, 0, 4, "", name, namelen) > 2
177 || x509_name_add_organizational_unit_name(name, &namelen, sizeof(name), ASN1_TAG_PrintableString, (uint8_t *)"CS", strlen("CS")) != 1
178 || format_bytes(stderr, 0, 4, "", name, namelen) > 2
179 || x509_name_add_common_name(name, &namelen, sizeof(name), ASN1_TAG_PrintableString, (uint8_t *)"CA", strlen("CA")) != 1
180 || format_bytes(stderr, 0, 4, "", name, namelen) > 2
181 ) {
182 error_print();
183 return 1;
184 }
185 format_bytes(stdout, 0, 0, "der ", name, namelen);
186 x509_name_print(stdout, 0, 0, "Name", name, namelen);
187 return 0;
188 }
189
test_x509_public_key_info(void)190 static int test_x509_public_key_info(void)
191 {
192 int err = 0;
193 SM2_KEY sm2_key;
194 SM2_KEY pub_key;
195 uint8_t buf[256];
196 const uint8_t *cp = buf;
197 uint8_t *p = buf;
198 size_t len = 0;
199 const uint8_t *d;
200 size_t dlen;
201
202
203 if (sm2_key_generate(&sm2_key) != 1
204 || x509_public_key_info_to_der(&sm2_key, &p, &len) != 1
205 || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1
206 || asn1_length_is_zero(len) != 1) {
207 error_print();
208 return 1;
209 }
210 x509_public_key_info_print(stdout, 0, 0, "PublicKeyInfo", d, dlen);
211 if (sm2_key_generate(&sm2_key) != 1
212 || x509_public_key_info_to_der(&sm2_key, &p, &len) != 1
213 || x509_public_key_info_from_der(&pub_key, &cp, &len) != 1
214 || asn1_length_is_zero(len) != 1) {
215 error_print();
216 return 1;
217 }
218 sm2_public_key_print(stdout, 0, 8, "ECPublicKey", &pub_key);
219
220 printf("%s() ok\n", __FUNCTION__);
221 return 0;
222 }
223
set_x509_name(uint8_t * name,size_t * namelen,size_t maxlen)224 static int set_x509_name(uint8_t *name, size_t *namelen, size_t maxlen)
225 {
226 *namelen = 0;
227 if (x509_name_add_country_name(name, namelen, maxlen, "CN") != 1
228 || x509_name_add_locality_name(name, namelen, maxlen, ASN1_TAG_PrintableString, (uint8_t *)"Haidian", strlen("Haidian")) != 1
229 || x509_name_add_state_or_province_name(name, namelen, maxlen, ASN1_TAG_PrintableString, (uint8_t *)"Beijing", strlen("Beijing")) != 1
230 || x509_name_add_organization_name(name, namelen, maxlen, ASN1_TAG_PrintableString, (uint8_t *)"PKU", strlen("PKU")) != 1
231 || x509_name_add_organizational_unit_name(name, namelen, maxlen, ASN1_TAG_PrintableString, (uint8_t *)"CS", strlen("CS")) != 1
232 || x509_name_add_common_name(name, namelen, maxlen, ASN1_TAG_PrintableString, (uint8_t *)"CA", strlen("CA")) != 1) {
233 error_print();
234 return -1;
235 }
236 return 1;
237 }
238
test_x509_tbs_cert(void)239 static int test_x509_tbs_cert(void)
240 {
241 uint8_t serial[20] = { 0x01, 0x00 };
242 size_t serial_len;
243 uint8_t issuer[256];
244 size_t issuer_len = 0;
245 time_t not_before, not_after;
246 uint8_t subject[256];
247 size_t subject_len = 0;
248 SM2_KEY sm2_key;
249 uint8_t buf[1024] = {0};
250 uint8_t *p = buf;
251 const uint8_t *cp = buf;
252 size_t len = 0;
253 const uint8_t *d;
254 size_t dlen;
255
256 set_x509_name(issuer, &issuer_len, sizeof(issuer));
257 time(¬_before);
258 x509_validity_add_days(¬_after, not_before, 365);
259 set_x509_name(subject, &subject_len, sizeof(subject));
260 sm2_key_generate(&sm2_key);
261
262 if (x509_tbs_cert_to_der(
263 X509_version_v3,
264 serial, sizeof(serial),
265 OID_sm2sign_with_sm3,
266 issuer, issuer_len,
267 not_before, not_after,
268 subject, subject_len,
269 &sm2_key,
270 NULL, 0,
271 NULL, 0,
272 NULL, 0,
273 &p, &len) != 1) {
274 error_print();
275 return -1;
276 }
277 format_bytes(stderr, 0, 0, "tbs_cert", buf, len);
278 if (asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1
279 || asn1_length_is_zero(len) != 1) {
280 error_print();
281 return -1;
282 }
283 x509_tbs_cert_print(stderr, 0, 4, "TBSCertificate", d, dlen);
284
285 return 0;
286 }
287
test_x509_cert_get(const uint8_t * cert,size_t certlen)288 static int test_x509_cert_get(const uint8_t *cert, size_t certlen)
289 {
290 const uint8_t *serial;
291 size_t serial_len;
292 const uint8_t *issuer;
293 size_t issuer_len;
294 const uint8_t *subject;
295 size_t subject_len;
296 SM2_KEY public_key;
297
298 if (x509_cert_get_issuer_and_serial_number(cert, certlen, &issuer, &issuer_len, &serial, &serial_len) != 1
299 || x509_cert_get_subject(cert, certlen, &subject, &subject_len) != 1
300 || x509_cert_get_subject_public_key(cert, certlen, &public_key) != 1) {
301 error_print();
302 return -1;
303 }
304 format_bytes(stderr, 0, 4, "SerialNumber", serial, serial_len);
305 x509_name_print(stderr, 0, 4, "Issuer", issuer, issuer_len);
306 x509_name_print(stderr, 0, 4, "Subject", subject, subject_len);
307 sm2_public_key_print(stderr, 0, 4, "SubjectPublicKey", &public_key);
308 return 0;
309 }
310
test_x509_cert(void)311 static int test_x509_cert(void)
312 {
313 uint8_t serial[20] = { 0x01, 0x00 };
314 size_t serial_len;
315 uint8_t issuer[256];
316 size_t issuer_len = 0;
317 time_t not_before, not_after;
318 uint8_t subject[256];
319 size_t subject_len = 0;
320 SM2_KEY sm2_key;
321 uint8_t cert[1024] = {0};
322 uint8_t *p = cert;
323 const uint8_t *cp = cert;
324 size_t certlen = 0;
325
326 set_x509_name(issuer, &issuer_len, sizeof(issuer));
327 time(¬_before);
328 x509_validity_add_days(¬_after, not_before, 365);
329 set_x509_name(subject, &subject_len, sizeof(subject));
330 sm2_key_generate(&sm2_key);
331
332 if (x509_cert_sign(
333 cert, &certlen, sizeof(cert),
334 X509_version_v3,
335 serial, sizeof(serial),
336 OID_sm2sign_with_sm3,
337 issuer, issuer_len,
338 not_before, not_after,
339 subject, subject_len,
340 &sm2_key,
341 NULL, 0,
342 NULL, 0,
343 NULL, 0,
344 &sm2_key, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID)) != 1) {
345 error_print();
346 return -1;
347 }
348 format_bytes(stderr, 0, 4, "cert", cert, certlen);
349 x509_cert_print(stderr, 0, 4, "Certificate", cert, certlen);
350
351 if (x509_cert_verify(cert, certlen, &sm2_key, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID)) != 1) {
352 error_print();
353 return -1;
354 }
355 printf("x509_cert_verify() success\n");
356
357 test_x509_cert_get(cert, certlen);
358
359
360 FILE *fp;
361
362 if (!(fp = fopen("cert.pem", "w"))) {
363 error_print();
364 return -1;
365 }
366
367 x509_cert_to_pem(cert, certlen, fp);
368 x509_cert_to_pem(cert, certlen, stderr);
369 fclose(fp);
370
371
372 if (!(fp = fopen("cert.pem", "r"))) {
373 error_print();
374 return -1;
375 }
376
377 memset(cert, 0, sizeof(cert));
378 if (x509_cert_from_pem(cert, &certlen, sizeof(cert), fp) != 1) {
379 error_print();
380 return -1;
381 }
382 x509_cert_print(stderr, 0, 4, "Certificate", cert, certlen);
383
384 return 0;
385 }
386
main(void)387 int main(void)
388 {
389 int err = 0;
390 err += test_x509_version();
391 err += test_x509_validity();
392 err += test_x509_attr_type_and_value();
393 err += test_x509_rdn();
394 err += test_x509_name();
395 err += test_x509_public_key_info();
396 err += test_x509_tbs_cert();
397 err += test_x509_cert();
398 return err;
399 }
400