1/* $NetBSD$ */ 2 3/* 4 * Copyright (c) 2006 Kungliga Tekniska H��gskolan 5 * (Royal Institute of Technology, Stockholm, Sweden). 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36#include "hx_locl.h" 37#include <krb5/pkcs10_asn1.h> 38 39struct hx509_request_data { 40 hx509_name name; 41 SubjectPublicKeyInfo key; 42 ExtKeyUsage eku; 43 GeneralNames san; 44}; 45 46/* 47 * 48 */ 49 50int 51hx509_request_init(hx509_context context, hx509_request *req) 52{ 53 *req = calloc(1, sizeof(**req)); 54 if (*req == NULL) 55 return ENOMEM; 56 57 return 0; 58} 59 60void 61hx509_request_free(hx509_request *req) 62{ 63 if ((*req)->name) 64 hx509_name_free(&(*req)->name); 65 free_SubjectPublicKeyInfo(&(*req)->key); 66 free_ExtKeyUsage(&(*req)->eku); 67 free_GeneralNames(&(*req)->san); 68 memset(*req, 0, sizeof(**req)); 69 free(*req); 70 *req = NULL; 71} 72 73int 74hx509_request_set_name(hx509_context context, 75 hx509_request req, 76 hx509_name name) 77{ 78 if (req->name) 79 hx509_name_free(&req->name); 80 if (name) { 81 int ret = hx509_name_copy(context, name, &req->name); 82 if (ret) 83 return ret; 84 } 85 return 0; 86} 87 88int 89hx509_request_get_name(hx509_context context, 90 hx509_request req, 91 hx509_name *name) 92{ 93 if (req->name == NULL) { 94 hx509_set_error_string(context, 0, EINVAL, "Request have no name"); 95 return EINVAL; 96 } 97 return hx509_name_copy(context, req->name, name); 98} 99 100int 101hx509_request_set_SubjectPublicKeyInfo(hx509_context context, 102 hx509_request req, 103 const SubjectPublicKeyInfo *key) 104{ 105 free_SubjectPublicKeyInfo(&req->key); 106 return copy_SubjectPublicKeyInfo(key, &req->key); 107} 108 109int 110hx509_request_get_SubjectPublicKeyInfo(hx509_context context, 111 hx509_request req, 112 SubjectPublicKeyInfo *key) 113{ 114 return copy_SubjectPublicKeyInfo(&req->key, key); 115} 116 117int 118_hx509_request_add_eku(hx509_context context, 119 hx509_request req, 120 const heim_oid *oid) 121{ 122 void *val; 123 int ret; 124 125 val = realloc(req->eku.val, sizeof(req->eku.val[0]) * (req->eku.len + 1)); 126 if (val == NULL) 127 return ENOMEM; 128 req->eku.val = val; 129 130 ret = der_copy_oid(oid, &req->eku.val[req->eku.len]); 131 if (ret) 132 return ret; 133 134 req->eku.len += 1; 135 136 return 0; 137} 138 139int 140_hx509_request_add_dns_name(hx509_context context, 141 hx509_request req, 142 const char *hostname) 143{ 144 GeneralName name; 145 146 memset(&name, 0, sizeof(name)); 147 name.element = choice_GeneralName_dNSName; 148 name.u.dNSName.data = rk_UNCONST(hostname); 149 name.u.dNSName.length = strlen(hostname); 150 151 return add_GeneralNames(&req->san, &name); 152} 153 154int 155_hx509_request_add_email(hx509_context context, 156 hx509_request req, 157 const char *email) 158{ 159 GeneralName name; 160 161 memset(&name, 0, sizeof(name)); 162 name.element = choice_GeneralName_rfc822Name; 163 name.u.dNSName.data = rk_UNCONST(email); 164 name.u.dNSName.length = strlen(email); 165 166 return add_GeneralNames(&req->san, &name); 167} 168 169 170 171int 172_hx509_request_to_pkcs10(hx509_context context, 173 const hx509_request req, 174 const hx509_private_key signer, 175 heim_octet_string *request) 176{ 177 CertificationRequest r; 178 heim_octet_string data, os; 179 int ret; 180 size_t size; 181 182 if (req->name == NULL) { 183 hx509_set_error_string(context, 0, EINVAL, 184 "PKCS10 needs to have a subject"); 185 return EINVAL; 186 } 187 188 memset(&r, 0, sizeof(r)); 189 memset(request, 0, sizeof(*request)); 190 191 r.certificationRequestInfo.version = pkcs10_v1; 192 193 ret = copy_Name(&req->name->der_name, 194 &r.certificationRequestInfo.subject); 195 if (ret) 196 goto out; 197 ret = copy_SubjectPublicKeyInfo(&req->key, 198 &r.certificationRequestInfo.subjectPKInfo); 199 if (ret) 200 goto out; 201 r.certificationRequestInfo.attributes = 202 calloc(1, sizeof(*r.certificationRequestInfo.attributes)); 203 if (r.certificationRequestInfo.attributes == NULL) { 204 ret = ENOMEM; 205 goto out; 206 } 207 208 ASN1_MALLOC_ENCODE(CertificationRequestInfo, data.data, data.length, 209 &r.certificationRequestInfo, &size, ret); 210 if (ret) 211 goto out; 212 if (data.length != size) 213 abort(); 214 215 ret = _hx509_create_signature(context, 216 signer, 217 _hx509_crypto_default_sig_alg, 218 &data, 219 &r.signatureAlgorithm, 220 &os); 221 free(data.data); 222 if (ret) 223 goto out; 224 r.signature.data = os.data; 225 r.signature.length = os.length * 8; 226 227 ASN1_MALLOC_ENCODE(CertificationRequest, data.data, data.length, 228 &r, &size, ret); 229 if (ret) 230 goto out; 231 if (data.length != size) 232 abort(); 233 234 *request = data; 235 236out: 237 free_CertificationRequest(&r); 238 239 return ret; 240} 241 242int 243_hx509_request_parse(hx509_context context, 244 const char *path, 245 hx509_request *req) 246{ 247 CertificationRequest r; 248 CertificationRequestInfo *rinfo; 249 hx509_name subject; 250 size_t len, size; 251 void *p; 252 int ret; 253 254 if (strncmp(path, "PKCS10:", 7) != 0) { 255 hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION, 256 "unsupport type in %s", path); 257 return HX509_UNSUPPORTED_OPERATION; 258 } 259 path += 7; 260 261 /* XXX PEM request */ 262 263 ret = rk_undumpdata(path, &p, &len); 264 if (ret) { 265 hx509_set_error_string(context, 0, ret, "Failed to map file %s", path); 266 return ret; 267 } 268 269 ret = decode_CertificationRequest(p, len, &r, &size); 270 rk_xfree(p); 271 if (ret) { 272 hx509_set_error_string(context, 0, ret, "Failed to decode %s", path); 273 return ret; 274 } 275 276 ret = hx509_request_init(context, req); 277 if (ret) { 278 free_CertificationRequest(&r); 279 return ret; 280 } 281 282 rinfo = &r.certificationRequestInfo; 283 284 ret = hx509_request_set_SubjectPublicKeyInfo(context, *req, 285 &rinfo->subjectPKInfo); 286 if (ret) { 287 free_CertificationRequest(&r); 288 hx509_request_free(req); 289 return ret; 290 } 291 292 ret = _hx509_name_from_Name(&rinfo->subject, &subject); 293 if (ret) { 294 free_CertificationRequest(&r); 295 hx509_request_free(req); 296 return ret; 297 } 298 ret = hx509_request_set_name(context, *req, subject); 299 hx509_name_free(&subject); 300 free_CertificationRequest(&r); 301 if (ret) { 302 hx509_request_free(req); 303 return ret; 304 } 305 306 return 0; 307} 308 309 310int 311_hx509_request_print(hx509_context context, hx509_request req, FILE *f) 312{ 313 int ret; 314 315 if (req->name) { 316 char *subject; 317 ret = hx509_name_to_string(req->name, &subject); 318 if (ret) { 319 hx509_set_error_string(context, 0, ret, "Failed to print name"); 320 return ret; 321 } 322 fprintf(f, "name: %s\n", subject); 323 free(subject); 324 } 325 326 return 0; 327} 328 329