-
Notifications
You must be signed in to change notification settings - Fork 1
/
x509cert.3
389 lines (385 loc) · 8.96 KB
/
x509cert.3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
.Dd May 6, 2021
.Dt X509CERT 3
.Os
.Sh NAME
.Nm x509cert_encode ,
.Nm x509cert_sign ,
.Nm x509cert_encode_req ,
.Nm x509cert_encode_cert ,
.Nm x509cert_encode_dn
.Nd construct and sign X.509 certificates and certificate requests
.Pp
.Nm x509cert_dn_string_rdn_len ,
.Nm x509cert_parse_dn_string
.Nd parse RFC 4514
.Em DistinguishedName
string representation
.Sh SYNOPSIS
.In x509cert.h
.Ft size_t
.Fn x509cert_encode "const struct x509cert_item *" "unsigned char *"
.Ft size_t
.Fn x509cert_sign "const struct x509cert_item *" "const struct x509cert_skey *" "const br_hash_class *" "unsigned char *"
.Ft size_t
.Fn x509cert_encode_req "const struct x509cert_req *" "unsigned char *"
.Vt x509cert_encoder x509cert_req_encoder ;
.Ft size_t
.Fn x509cert_encode_cert "const struct x509cert_cert *" "unsigned char *"
.Vt x509cert_encoder x509cert_cert_encoder ;
.Ft size_t
.Fn x509cert_encode_dn "const struct x509cert_dn *" "unsigned char *"
.Vt x509cert_encoder x509cert_dn_encoder ;
.Ft size_t
.Fn x509cert_dn_string_rdn_len "const char *"
.Ft int
.Fn x509cert_parse_dn_string "struct x509cert_rdn *" "char *"
.Sh DESCRIPTION
Most functions in
.Nm libx509cert
follow a similar pattern.
They take a pointer to a buffer in which to encode some ASN.1
structure, and return the encoded length, or 0 if it cannot be
encoded.
In order to determine an appropriate size for this buffer, the
function should first be called with
.Dv NULL
to compute the encoded size, and then again with an allocated buffer
of at least this size.
This pattern is captured with the
.Vt x509cert_encoder
function typedef.
.Pp
A general ASN.1 item is represented with
.Vt struct x509cert_item ,
which has the following members:
.Bl -tag -offset indent -width Ds
.It Va tag
The item tag.
.It Va len
The length of the item contents in bytes.
.It Va val
The item contents.
.It Va enc
An optional custom encoder for the item.
.El
.Pp
The
.Fn x509cert_encode
function encodes an ASN.1 item into a buffer.
If
.Va enc
is
.Dv NULL ,
the default encoder is used, which encodes
.Va tag
and
.Va len ,
then copies
.Va len
bytes from
.Va val
into the buffer.
If
.Va tag
is 0,
.Va val
is assumed to be pre-encoded, and no tag-length header is added.
Otherwise, the
.Va enc
function is called with the item as its argument, which encodes the
item some other way.
In this case,
.Va val
might point to some structure, with
.Va tag
and
.Va len
unused.
.Pp
The
.Fn x509cert_sign
function DER-encodes a ASN.1 item along with its signature as an
X.509
.Em SIGNED{...}
structure into a buffer, returning its length.
If the buffer is
.Dv NULL ,
no encoding or signing takes place.
Instead, the maximum length of the encoded item is returned.
The actual length may be several bytes smaller.
The signature algorithm used is determined by the type of the private
key and the hash algorithm.
Supported key types are
.Li BR_KEYTYPE_RSA
(up to 4096 bit)
and
.Li BR_KEYTYPE_EC
(secp256r1, secp384r1, secp521r1).
.Pp
A certificate request is described by
.Vt struct x509cert_req ,
which has the following members:
.Bl -tag -width alts_len -offset indent
.It Va subject
The subject of the requested certificate.
Must encode as an X.501
.Em DistinguishedName .
.It Va pkey
The public key of the requested certificate.
This must match the key passed to
.Fn x509cert_sign .
.It Va alts
An array of alternate names to add in a
.Em subjectAltName
extension.
.It Va alts_len
The length of the
.Va alts
array.
.El
.Pp
The
.Fn x509cert_encode_req
function DER-encodes a PKCS#10
.Em CertificateRequestInfo
into a buffer.
If
.Va alts_len
is positive, an extension request is added for
.Em subjectAltName
containing the alternate names given in
.Va alts .
Each one must have a one of the following tags and correseponding
value type:
.Bl -tag -offset indent -width "X509CERT_SAN_RFC822NAME"
.It Dv X509CERT_SAN_OTHERNAME
.Em SEQUENCE { OID, ANY }
.It Dv X509CERT_SAN_RFC822NAME
.Em IA5String
.It Dv X509CERT_SAN_DNSNAME
.Em IA5String
.It Dv X509CERT_SAN_URI
.Em IA5String
.It Dv X509CERT_SAN_IPADDRESS
.Em OCTET STRING
.El
.Pp
A certificate is described by
.Vt struct x509cert_cert ,
which has the following members:
.Bl -tag -offset ident -width notbefore
.It Va req
An inner
.Vt struct x509cert_req
is used for its
.Va subject ,
.Va pkey ,
.Va alts ,
and
.Va alts_len
members, which have the same semantics as they do for
.Fn x509cert_encode_req
except that
.Va pkey
needn't match the signing key.
.It Va serial
The serial number of the certificate, in big-endian format.
Must be unique for each certificate issued by a given CA.
.It Va key_type
The type of the CA's signing key.
This must match the key passed to
.Fn x509cert_sign .
.It Va hash_id
The ID of the hash used for signing the certificate.
This must match the hash passed to
.Fn x509cert_sign .
.It Va issuer
The name of the certificate issuer.
Must encode as an X.501
.Em DistinguishedName .
.It Va notbefore
The Unix time at which the certificate becomes valid.
.It Va notafter
The Unix time after which the certificate is no longer valid.
.It Va ca
Indicates whether or not the subject is a certificate authority.
.El
.Pp
The
.Fn x509cert_encode_cert
function DER-encodes an X.509
.Em TBSCertificate
into a buffer.
If
.Va ca
is non-zero, a
.Em basicConstraints
extension is added with the
.Li cA
field set to
.Dv TRUE ,
indicating that the subject is a certificate authority.
.Pp
A distinguished name is represented with
.Vt struct x509cert_dn ,
which has the following members:
.Bl -tag -offset indent -width rdn_len
.It Va rdn
An array of relative distinguished names, starting with the most
significant.
.It Va rdn_len
The length of the
.Va rdn
array.
.El
.Pp
Each RDN has type
.Vt struct x509cert_rdn ,
which has the following members:
.Bl -tag -offset indent -width Ds
.It Va oid
A pre-encoded OID indicating the attribute type.
.It Va val
The attribute value, which must be a
.Em PrintableString
or
.Em UTF8String .
.El
.Pp
The
.Fn x509cert_encode_dn
function DER-encodes an X.501
.Em DistinguishedName
into a buffer.
RDNs with multiple attributes are not supported.
.Pp
The
.Fn x509cert_dn_string_rdn_len
function determines the number of RDNs represented in a RFC 4514
DN string.
.Pp
The
.Fn x509cert_parse_dn_string
function parses the RFC 4514 DN string representation (for example,
.Li C=US,CN=example.com )
into an array of RDNs.
Multi-valued RDNs are not supported.
The array must be large enough for all RDNs, the number of which
can be determined with
.Fn x509cert_dn_string_rdn_len .
The string buffer is rewritten in-place with RDN values and encoded
OIDs.
.Pp
The following attribute names are supported:
.Bl -tag -offset indent -width Ds
.It CN
.Em commonName
(OID 2.5.4.3)
.It L
.Em localityName
(OID 2.5.4.7)
.It ST
.Em stateOrProvinceName
(OID 2.5.4.8)
.It O
.Em organizationName
(OID 2.5.4.10)
.It OU
.Em organizationalUnitName
(OID 2.5.4.11)
.It C
.Em countryName
(OID 2.5.4.6)
.It STREET
.Em streetAddress
(OID 2.5.4.9)
.It DC
.Em domainComponent
(OID 0.9.2342.19200300.100.1.25)
.It UID
.Em userId
(OID 0.9.2342.19200300.100.1.1)
.El
.Pp
The OIDs for these attributes are also available for explicit
.Vt struct x509cert_dn
construction as
.Va x509cert_oid_* .
.Sh RETURN VALUES
The
.Fn x509cert_encode ,
.Fn x509cert_encode_req ,
.Fn x509cert_encode_cert ,
and
.Fn x509cert_encode_dn
functions return the encoded length of the ASN.1 item, or 0 if the
item cannot be encoded.
.Pp
The
.Fn x509cert_sign
function returns the
.Em maximum
encoded length of the ASN.1
.Em SIGNED{...}
structure if the buffer is
.Dv NULL ,
and the actual encoded length otherwise.
If the item cannot be encoded, or there is an error computing the
signature, 0 is returned.
.Pp
The
.Fn x509cert_dn_string_rdn_len
function returns the number of RDNs described in the string.
.Pp
The
.Fn x509cert_parse_dn_string
function returns 1 on success, or 0 if the string is invalid or the
buffer is not large enough.
.Sh EXAMPLES
Creating a self-signed certificate for example.com:
.Bd -literal -offset indent
#include <stdlib.h>
#include <x509cert.h>
br_x509_certificate
selfsigned(const struct x509cert_skey *skey, const br_x509_pkey *pkey)
{
struct x509cert_dn dn = {
.rdn = &(struct x509cert_rdn){
.oid = x509cert_oid_CN,
.val.tag = X509CERT_ASN1_UTF8STRING,
.val.len = 11,
.val.val = "example.com",
},
.rdn_len = 1,
};
struct x509cert_cert cert = {
.req = &(struct x509cert_req){
.subject = {.enc = x509cert_dn_encoder, .val = &dn},
.pkey = *pkey,
},
.key_type = skey->type,
.hash_id = br_sha256_ID,
.issuer = {.enc = x509cert_dn_encoder, .val = &dn}
};
struct x509cert_item cert_item = {
.enc = x509cert_cert_encoder,
.val = &cert,
};
size_t len;
unsigned char *buf;
cert.notbefore = time(NULL);
cert.notafter = cert.notbefore + 2592000;
/* calculate maximum length */
len = x509cert_sign(&cert_item, skey, &br_sha256_vtable, NULL);
if (len == 0 || !(buf = malloc(len)))
return (br_x509_certificate){0};
len = x509cert_sign(&cert_item, skey, &br_sha256_vtable, buf);
if (len == 0) {
free(buf);
return (br_x509_certificate){0};
}
return (br_x509_certificate){.data = buf, .data_len = len};
}
.Ed
.Sh SEE ALSO
.Xr x509cert 1