monotone

monotone Mtn Source Tree

Root/botan/x509self.cpp

1/*************************************************
2* X.509 Certificate Authority Source File *
3* (C) 1999-2005 The Botan Project *
4*************************************************/
5
6#include <botan/x509self.h>
7#include <botan/x509_ca.h>
8#include <botan/conf.h>
9#include <botan/look_pk.h>
10#include <botan/oids.h>
11#include <botan/pipe.h>
12#include <memory>
13
14namespace Botan {
15
16namespace {
17
18/*************************************************
19* Shared setup for self-signed items *
20*************************************************/
21MemoryVector<byte> shared_setup(const X509_Cert_Options& opts,
22 const PKCS8_PrivateKey& key)
23 {
24 const PKCS8_PrivateKey* key_pointer = &key;
25 if(!dynamic_cast<const PK_Signing_Key*>(key_pointer))
26 throw Invalid_Argument("Key type " + key.algo_name() + " cannot sign");
27
28 opts.sanity_check();
29
30 Pipe key_encoder;
31 key_encoder.start_msg();
32 X509::encode(key, key_encoder, RAW_BER);
33 key_encoder.end_msg();
34
35 return key_encoder.read_all();
36 }
37
38/*************************************************
39* Load information from the X509_Cert_Options *
40*************************************************/
41void load_info(const X509_Cert_Options& opts, X509_DN& subject_dn,
42 AlternativeName& subject_alt)
43 {
44 subject_dn.add_attribute("X520.CommonName", opts.common_name);
45 subject_dn.add_attribute("X520.Country", opts.country);
46 subject_dn.add_attribute("X520.State", opts.state);
47 subject_dn.add_attribute("X520.Locality", opts.locality);
48 subject_dn.add_attribute("X520.Organization", opts.organization);
49 subject_dn.add_attribute("X520.OrganizationalUnit", opts.org_unit);
50 subject_dn.add_attribute("X520.SerialNumber", opts.serial_number);
51 subject_alt = AlternativeName(opts.email, opts.uri, opts.dns);
52 subject_alt.add_othername(OIDS::lookup("PKIX.XMPPAddr"),
53 opts.xmpp, UTF8_STRING);
54 }
55
56/*************************************************
57* Choose a signing format for the key *
58*************************************************/
59PK_Signer* choose_sig_format(const PKCS8_PrivateKey& key,
60 AlgorithmIdentifier& sig_algo)
61 {
62 std::string padding;
63 Signature_Format format;
64 Config::choose_sig_format(key.algo_name(), padding, format);
65
66 sig_algo.oid = OIDS::lookup(key.algo_name() + "/" + padding);
67 sig_algo.parameters = key.DER_encode_params();
68
69 const PK_Signing_Key& sig_key = dynamic_cast<const PK_Signing_Key&>(key);
70
71 return get_pk_signer(sig_key, padding, format);
72 }
73
74/*************************************************
75* Encode an attribute for PKCS #10 request *
76*************************************************/
77void do_attribute(DER_Encoder& tbs_req, DER_Encoder& attr_bits,
78 const std::string& oid_str)
79 {
80 Attribute attr(OIDS::lookup(oid_str), attr_bits.get_contents());
81 DER::encode(tbs_req, attr);
82 }
83
84/*************************************************
85* Encode an Extension for a PKCS #10 request *
86*************************************************/
87void do_ext(DER_Encoder& attr_encoder, DER_Encoder& extn_bits,
88 const std::string& oid)
89 {
90 Extension extn(oid, extn_bits.get_contents());
91 DER::encode(attr_encoder, extn);
92 }
93
94/*************************************************
95* Encode X.509 extensions for a PKCS #10 request *
96*************************************************/
97void encode_extensions(DER_Encoder& attr_encoder,
98 const AlternativeName& subject_alt,
99 bool is_CA, u32bit path_limit,
100 Key_Constraints constraints,
101 const std::vector<OID>& ex_constraints)
102 {
103 DER_Encoder v3_ext;
104
105 attr_encoder.start_sequence();
106 if(is_CA)
107 {
108 v3_ext.start_sequence();
109 DER::encode(v3_ext, true);
110 if(path_limit != NO_CERT_PATH_LIMIT)
111 DER::encode(v3_ext, path_limit);
112 v3_ext.end_sequence();
113 do_ext(attr_encoder, v3_ext, "X509v3.BasicConstraints");
114 }
115
116 if(subject_alt.has_items())
117 {
118 DER::encode(v3_ext, subject_alt);
119 do_ext(attr_encoder, v3_ext, "X509v3.SubjectAlternativeName");
120 }
121
122 if(constraints != NO_CONSTRAINTS)
123 {
124 DER::encode(v3_ext, constraints);
125 do_ext(attr_encoder, v3_ext, "X509v3.KeyUsage");
126 }
127
128 if(ex_constraints.size())
129 {
130 v3_ext.start_sequence();
131 for(u32bit j = 0; j != ex_constraints.size(); j++)
132 DER::encode(v3_ext, ex_constraints[j]);
133 v3_ext.end_sequence();
134 do_ext(attr_encoder, v3_ext, "X509v3.ExtendedKeyUsage");
135 }
136 attr_encoder.end_sequence();
137 }
138
139}
140
141namespace X509 {
142
143/*************************************************
144* Create a new self-signed X.509 certificate *
145*************************************************/
146X509_Certificate create_self_signed_cert(const X509_Cert_Options& opts,
147 const PKCS8_PrivateKey& key)
148 {
149 AlgorithmIdentifier sig_algo;
150 X509_DN subject_dn;
151 AlternativeName subject_alt;
152
153 MemoryVector<byte> pub_key = shared_setup(opts, key);
154 std::auto_ptr<PK_Signer> signer(choose_sig_format(key, sig_algo));
155 load_info(opts, subject_dn, subject_alt);
156
157 Key_Constraints constraints;
158 if(opts.is_CA)
159 constraints = Key_Constraints(KEY_CERT_SIGN | CRL_SIGN);
160 else
161 constraints = find_constraints(key, opts.constraints);
162
163 return X509_CA::make_cert(signer.get(), sig_algo, pub_key,
164 MemoryVector<byte>(), opts.start, opts.end,
165 subject_dn, subject_dn,
166 opts.is_CA, opts.path_limit,
167 subject_alt, constraints, opts.ex_constraints);
168 }
169
170/*************************************************
171* Create a PKCS #10 certificate request *
172*************************************************/
173PKCS10_Request create_cert_req(const X509_Cert_Options& opts,
174 const PKCS8_PrivateKey& key)
175 {
176 AlgorithmIdentifier sig_algo;
177 X509_DN subject_dn;
178 AlternativeName subject_alt;
179
180 MemoryVector<byte> pub_key = shared_setup(opts, key);
181 std::auto_ptr<PK_Signer> signer(choose_sig_format(key, sig_algo));
182 load_info(opts, subject_dn, subject_alt);
183
184 const u32bit PKCS10_VERSION = 0;
185
186 DER_Encoder tbs_req;
187
188 tbs_req.start_sequence();
189 DER::encode(tbs_req, PKCS10_VERSION);
190 DER::encode(tbs_req, subject_dn);
191 tbs_req.add_raw_octets(pub_key);
192
193 tbs_req.start_explicit(ASN1_Tag(0));
194
195 DER_Encoder attr_encoder;
196
197 if(opts.challenge != "")
198 {
199 ASN1_String challenge(opts.challenge, DIRECTORY_STRING);
200 DER::encode(attr_encoder, challenge);
201 do_attribute(tbs_req, attr_encoder, "PKCS9.ChallengePassword");
202 }
203
204 Key_Constraints constraints;
205 if(opts.is_CA)
206 constraints = Key_Constraints(KEY_CERT_SIGN | CRL_SIGN);
207 else
208 constraints = find_constraints(key, opts.constraints);
209
210 encode_extensions(attr_encoder, subject_alt, opts.is_CA, opts.path_limit,
211 constraints, opts.ex_constraints);
212 do_attribute(tbs_req, attr_encoder, "PKCS9.ExtensionRequest");
213
214 tbs_req.end_explicit(ASN1_Tag(0));
215
216 tbs_req.end_sequence();
217
218 MemoryVector<byte> tbs_bits = tbs_req.get_contents();
219 MemoryVector<byte> sig = signer->sign_message(tbs_bits);
220
221 DER_Encoder full_req;
222 full_req.start_sequence();
223 full_req.add_raw_octets(tbs_bits);
224 DER::encode(full_req, sig_algo);
225 DER::encode(full_req, sig, BIT_STRING);
226 full_req.end_sequence();
227
228 DataSource_Memory source(full_req.get_contents());
229
230 return PKCS10_Request(source);
231 }
232
233}
234
235}

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status