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