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 <stdint.h>
15 #include <assert.h>
16 #include <gmssl/sm2.h>
17 #include <gmssl/oid.h>
18 #include <gmssl/pem.h>
19 #include <gmssl/asn1.h>
20 #include <gmssl/x509_str.h>
21 #include <gmssl/error.h>
22
23 /*
24 DirectoryString ::= CHOICE {
25 teletexString TeletexString (SIZE (1..MAX)),
26 printableString PrintableString (SIZE (1..MAX)),
27 universalString UniversalString (SIZE (1..MAX)),
28 utf8String UTF8String (SIZE (1..MAX)),
29 bmpString BMPString (SIZE (1..MAX)) }
30
31 BMPString has zeros!
32 "Cert" in BMPStirng is 00 43 00 65 00 72 00 74
33
34 RDN 中很多值都是这个类型,但是有特定的长度限制,因此这个函数应该增加一个长度限制选项。
35 */
36
37
x509_directory_name_check(int tag,const uint8_t * d,size_t dlen)38 int x509_directory_name_check(int tag, const uint8_t *d, size_t dlen)
39 {
40 switch (tag) {
41 case ASN1_TAG_TeletexString:
42 case ASN1_TAG_PrintableString:
43 case ASN1_TAG_UniversalString:
44 case ASN1_TAG_UTF8String:
45 if (d && strnlen((char *)d, dlen) != dlen) {
46 error_print();
47 return -1;
48 }
49 break;
50 case ASN1_TAG_BMPString:
51 if (d && dlen % 2) {
52 error_print();
53 return -1;
54 }
55 break;
56 default:
57 error_print();
58 return -1;
59 }
60 return 1;
61 }
62
x509_directory_name_check_ex(int tag,const uint8_t * d,size_t dlen,size_t minlen,size_t maxlen)63 int x509_directory_name_check_ex(int tag, const uint8_t *d, size_t dlen, size_t minlen, size_t maxlen)
64 {
65 if (x509_directory_name_check(tag, d, dlen) != 1) {
66 error_print();
67 return -1;
68 }
69 if (dlen < minlen || dlen > maxlen) {
70 printf("%s %d: dlen = %zu, minlen = %zu, maxlne = %zu\n", __FILE__, __LINE__, dlen, minlen, maxlen);
71 error_print();
72 return -1;
73 }
74 return 1;
75 }
76
x509_directory_name_to_der(int tag,const uint8_t * d,size_t dlen,uint8_t ** out,size_t * outlen)77 int x509_directory_name_to_der(int tag, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen)
78 {
79 int ret;
80 if (x509_directory_name_check(tag, d, dlen) != 1) {
81 error_print();
82 return -1;
83 }
84 if ((ret = asn1_type_to_der(tag, d, dlen, out, outlen)) != 1) {
85 if (ret < 0) error_print();
86 return ret;
87 }
88 return 1;
89 }
90
x509_directory_name_from_der(int * tag,const uint8_t ** d,size_t * dlen,const uint8_t ** in,size_t * inlen)91 int x509_directory_name_from_der(int *tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen)
92 {
93 int ret;
94
95 if ((ret = asn1_tag_get(tag, in, inlen)) != 1) {
96 if (ret < 0) error_print();
97 return ret;
98 }
99 switch (*tag) {
100 case ASN1_TAG_TeletexString:
101 case ASN1_TAG_PrintableString:
102 case ASN1_TAG_UniversalString:
103 case ASN1_TAG_UTF8String:
104 case ASN1_TAG_BMPString:
105 break;
106 default:
107 return 0;
108 }
109
110 if ((ret = asn1_any_type_from_der(tag, d, dlen, in, inlen)) != 1) {
111 if (ret < 0) error_print();
112 return ret;
113 }
114 if (x509_directory_name_check(*tag, *d, *dlen) != 1) {
115 error_print();
116 return -1;
117 }
118 return 1;
119 }
120
x509_explicit_directory_name_to_der(int index,int tag,const uint8_t * d,size_t dlen,uint8_t ** out,size_t * outlen)121 int x509_explicit_directory_name_to_der(int index, int tag, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen)
122 {
123 int ret;
124 size_t len = 0;
125
126 if ((ret = x509_directory_name_to_der(tag, d, dlen, NULL, &len)) != 1) {
127 if (ret < 0) error_print();
128 return ret;
129 }
130 if (asn1_explicit_header_to_der(index, len, out, outlen) != 1
131 || x509_directory_name_to_der(tag, d, dlen, out, outlen) != 1) {
132 error_print();
133 return -1;
134 }
135 return 1;
136 }
137
x509_explicit_directory_name_from_der(int index,int * tag,const uint8_t ** d,size_t * dlen,const uint8_t ** in,size_t * inlen)138 int x509_explicit_directory_name_from_der(int index, int *tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen)
139 {
140 int ret;
141 const uint8_t *p;
142 size_t len;
143
144 if ((ret = asn1_explicit_from_der(index, &p, &len, in, inlen)) != 1) {
145 if (ret < 0) error_print();
146 return ret;
147 }
148 if (x509_directory_name_from_der(tag, d, dlen, &p, &len) != 1
149 || asn1_length_is_zero(len) != 1) {
150 error_print();
151 return -1;
152 }
153 return 1;
154 }
155
x509_directory_name_print(FILE * fp,int fmt,int ind,const char * label,int tag,const uint8_t * d,size_t dlen)156 int x509_directory_name_print(FILE *fp, int fmt, int ind, const char *label, int tag, const uint8_t *d, size_t dlen)
157 {
158 return asn1_string_print(fp, fmt, ind, label, tag, d, dlen);
159 }
160
x509_display_text_check(int tag,const uint8_t * d,size_t dlen)161 int x509_display_text_check(int tag, const uint8_t *d, size_t dlen)
162 {
163 switch (tag) {
164 case ASN1_TAG_IA5String:
165 case ASN1_TAG_VisibleString:
166 case ASN1_TAG_UTF8String:
167 if (d && strnlen((char *)d, dlen) != dlen) {
168 error_print();
169 return -1;
170 }
171 break;
172 case ASN1_TAG_BMPString:
173 if (d && dlen % 2) {
174 error_print();
175 return -1;
176 }
177 break;
178 default:
179 error_print();
180 return -1;
181 }
182 if (dlen < X509_DISPLAY_TEXT_MIN_LEN || dlen > X509_DISPLAY_TEXT_MAX_LEN) {
183 error_print();
184 return -1;
185 }
186 return 1;
187 }
188
x509_display_text_to_der(int tag,const uint8_t * d,size_t dlen,uint8_t ** out,size_t * outlen)189 int x509_display_text_to_der(int tag, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen)
190 {
191 int ret;
192 if (x509_display_text_check(tag, d, dlen) != 1) {
193 error_print();
194 return -1;
195 }
196 if ((ret = asn1_type_to_der(tag, d, dlen, out, outlen)) != 1) {
197 if (ret < 0) error_print();
198 return ret;
199 }
200 return 1;
201 }
202
x509_display_text_from_der(int * tag,const uint8_t ** d,size_t * dlen,const uint8_t ** in,size_t * inlen)203 int x509_display_text_from_der(int *tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen)
204 {
205 int ret;
206
207 if ((ret = asn1_tag_get(tag, in, inlen)) != 1) {
208 if (ret < 0) error_print();
209 return ret;
210 }
211 switch (*tag) {
212 case ASN1_TAG_IA5String:
213 case ASN1_TAG_VisibleString:
214 case ASN1_TAG_UTF8String:
215 case ASN1_TAG_BMPString:
216 break;
217 default:
218 return 0;
219 }
220
221 if ((ret = asn1_any_type_from_der(tag, d, dlen, in, inlen)) != 1) {
222 if (ret < 0) error_print();
223 return ret;
224 }
225 if (x509_display_text_check(*tag, *d, *dlen) != 1) {
226 error_print();
227 return -1;
228 }
229 return 1;
230 }
231
x509_display_text_print(FILE * fp,int fmt,int ind,const char * label,int tag,const uint8_t * d,size_t dlen)232 int x509_display_text_print(FILE *fp, int fmt, int ind, const char *label, int tag, const uint8_t *d, size_t dlen)
233 {
234 return asn1_string_print(fp, fmt, ind, label, tag, d, dlen);
235 }
236