1178825Sdfr/* 2233294Sstas * Copyright (c) 2006 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 5178825Sdfr * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 9178825Sdfr * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 12178825Sdfr * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 16178825Sdfr * 17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 18233294Sstas * may be used to endorse or promote products derived from this software 19233294Sstas * without specific prior written permission. 20178825Sdfr * 21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31233294Sstas * SUCH DAMAGE. 32178825Sdfr */ 33178825Sdfr 34178825Sdfr#include "hx_locl.h" 35178825Sdfr#include <pkcs10_asn1.h> 36178825Sdfr 37178825Sdfrstruct hx509_request_data { 38178825Sdfr hx509_name name; 39178825Sdfr SubjectPublicKeyInfo key; 40178825Sdfr ExtKeyUsage eku; 41178825Sdfr GeneralNames san; 42178825Sdfr}; 43178825Sdfr 44178825Sdfr/* 45178825Sdfr * 46178825Sdfr */ 47178825Sdfr 48178825Sdfrint 49233294Sstashx509_request_init(hx509_context context, hx509_request *req) 50178825Sdfr{ 51178825Sdfr *req = calloc(1, sizeof(**req)); 52178825Sdfr if (*req == NULL) 53178825Sdfr return ENOMEM; 54178825Sdfr 55178825Sdfr return 0; 56178825Sdfr} 57178825Sdfr 58178825Sdfrvoid 59233294Sstashx509_request_free(hx509_request *req) 60178825Sdfr{ 61178825Sdfr if ((*req)->name) 62178825Sdfr hx509_name_free(&(*req)->name); 63178825Sdfr free_SubjectPublicKeyInfo(&(*req)->key); 64178825Sdfr free_ExtKeyUsage(&(*req)->eku); 65178825Sdfr free_GeneralNames(&(*req)->san); 66178825Sdfr memset(*req, 0, sizeof(**req)); 67178825Sdfr free(*req); 68178825Sdfr *req = NULL; 69178825Sdfr} 70178825Sdfr 71178825Sdfrint 72233294Sstashx509_request_set_name(hx509_context context, 73178825Sdfr hx509_request req, 74178825Sdfr hx509_name name) 75178825Sdfr{ 76178825Sdfr if (req->name) 77178825Sdfr hx509_name_free(&req->name); 78178825Sdfr if (name) { 79178825Sdfr int ret = hx509_name_copy(context, name, &req->name); 80178825Sdfr if (ret) 81178825Sdfr return ret; 82178825Sdfr } 83178825Sdfr return 0; 84178825Sdfr} 85178825Sdfr 86178825Sdfrint 87233294Sstashx509_request_get_name(hx509_context context, 88178825Sdfr hx509_request req, 89178825Sdfr hx509_name *name) 90178825Sdfr{ 91178825Sdfr if (req->name == NULL) { 92178825Sdfr hx509_set_error_string(context, 0, EINVAL, "Request have no name"); 93178825Sdfr return EINVAL; 94178825Sdfr } 95178825Sdfr return hx509_name_copy(context, req->name, name); 96178825Sdfr} 97178825Sdfr 98178825Sdfrint 99233294Sstashx509_request_set_SubjectPublicKeyInfo(hx509_context context, 100178825Sdfr hx509_request req, 101178825Sdfr const SubjectPublicKeyInfo *key) 102178825Sdfr{ 103178825Sdfr free_SubjectPublicKeyInfo(&req->key); 104178825Sdfr return copy_SubjectPublicKeyInfo(key, &req->key); 105178825Sdfr} 106178825Sdfr 107178825Sdfrint 108233294Sstashx509_request_get_SubjectPublicKeyInfo(hx509_context context, 109178825Sdfr hx509_request req, 110178825Sdfr SubjectPublicKeyInfo *key) 111178825Sdfr{ 112178825Sdfr return copy_SubjectPublicKeyInfo(&req->key, key); 113178825Sdfr} 114178825Sdfr 115178825Sdfrint 116178825Sdfr_hx509_request_add_eku(hx509_context context, 117178825Sdfr hx509_request req, 118178825Sdfr const heim_oid *oid) 119178825Sdfr{ 120178825Sdfr void *val; 121178825Sdfr int ret; 122178825Sdfr 123178825Sdfr val = realloc(req->eku.val, sizeof(req->eku.val[0]) * (req->eku.len + 1)); 124178825Sdfr if (val == NULL) 125178825Sdfr return ENOMEM; 126178825Sdfr req->eku.val = val; 127178825Sdfr 128178825Sdfr ret = der_copy_oid(oid, &req->eku.val[req->eku.len]); 129178825Sdfr if (ret) 130178825Sdfr return ret; 131178825Sdfr 132178825Sdfr req->eku.len += 1; 133178825Sdfr 134178825Sdfr return 0; 135178825Sdfr} 136178825Sdfr 137178825Sdfrint 138178825Sdfr_hx509_request_add_dns_name(hx509_context context, 139178825Sdfr hx509_request req, 140178825Sdfr const char *hostname) 141178825Sdfr{ 142178825Sdfr GeneralName name; 143178825Sdfr 144178825Sdfr memset(&name, 0, sizeof(name)); 145178825Sdfr name.element = choice_GeneralName_dNSName; 146233294Sstas name.u.dNSName.data = rk_UNCONST(hostname); 147233294Sstas name.u.dNSName.length = strlen(hostname); 148178825Sdfr 149178825Sdfr return add_GeneralNames(&req->san, &name); 150178825Sdfr} 151178825Sdfr 152178825Sdfrint 153178825Sdfr_hx509_request_add_email(hx509_context context, 154178825Sdfr hx509_request req, 155178825Sdfr const char *email) 156178825Sdfr{ 157178825Sdfr GeneralName name; 158178825Sdfr 159178825Sdfr memset(&name, 0, sizeof(name)); 160178825Sdfr name.element = choice_GeneralName_rfc822Name; 161233294Sstas name.u.dNSName.data = rk_UNCONST(email); 162233294Sstas name.u.dNSName.length = strlen(email); 163178825Sdfr 164178825Sdfr return add_GeneralNames(&req->san, &name); 165178825Sdfr} 166178825Sdfr 167178825Sdfr 168178825Sdfr 169178825Sdfrint 170178825Sdfr_hx509_request_to_pkcs10(hx509_context context, 171178825Sdfr const hx509_request req, 172178825Sdfr const hx509_private_key signer, 173178825Sdfr heim_octet_string *request) 174178825Sdfr{ 175178825Sdfr CertificationRequest r; 176178825Sdfr heim_octet_string data, os; 177178825Sdfr int ret; 178178825Sdfr size_t size; 179178825Sdfr 180178825Sdfr if (req->name == NULL) { 181178825Sdfr hx509_set_error_string(context, 0, EINVAL, 182178825Sdfr "PKCS10 needs to have a subject"); 183178825Sdfr return EINVAL; 184178825Sdfr } 185178825Sdfr 186178825Sdfr memset(&r, 0, sizeof(r)); 187178825Sdfr memset(request, 0, sizeof(*request)); 188178825Sdfr 189178825Sdfr r.certificationRequestInfo.version = pkcs10_v1; 190178825Sdfr 191178825Sdfr ret = copy_Name(&req->name->der_name, 192178825Sdfr &r.certificationRequestInfo.subject); 193178825Sdfr if (ret) 194178825Sdfr goto out; 195178825Sdfr ret = copy_SubjectPublicKeyInfo(&req->key, 196178825Sdfr &r.certificationRequestInfo.subjectPKInfo); 197178825Sdfr if (ret) 198178825Sdfr goto out; 199233294Sstas r.certificationRequestInfo.attributes = 200178825Sdfr calloc(1, sizeof(*r.certificationRequestInfo.attributes)); 201178825Sdfr if (r.certificationRequestInfo.attributes == NULL) { 202178825Sdfr ret = ENOMEM; 203178825Sdfr goto out; 204178825Sdfr } 205178825Sdfr 206233294Sstas ASN1_MALLOC_ENCODE(CertificationRequestInfo, data.data, data.length, 207178825Sdfr &r.certificationRequestInfo, &size, ret); 208178825Sdfr if (ret) 209178825Sdfr goto out; 210178825Sdfr if (data.length != size) 211178825Sdfr abort(); 212178825Sdfr 213178825Sdfr ret = _hx509_create_signature(context, 214178825Sdfr signer, 215178825Sdfr _hx509_crypto_default_sig_alg, 216178825Sdfr &data, 217178825Sdfr &r.signatureAlgorithm, 218178825Sdfr &os); 219178825Sdfr free(data.data); 220178825Sdfr if (ret) 221178825Sdfr goto out; 222178825Sdfr r.signature.data = os.data; 223178825Sdfr r.signature.length = os.length * 8; 224178825Sdfr 225178825Sdfr ASN1_MALLOC_ENCODE(CertificationRequest, data.data, data.length, 226178825Sdfr &r, &size, ret); 227178825Sdfr if (ret) 228178825Sdfr goto out; 229178825Sdfr if (data.length != size) 230178825Sdfr abort(); 231178825Sdfr 232178825Sdfr *request = data; 233178825Sdfr 234178825Sdfrout: 235178825Sdfr free_CertificationRequest(&r); 236178825Sdfr 237178825Sdfr return ret; 238178825Sdfr} 239178825Sdfr 240178825Sdfrint 241233294Sstas_hx509_request_parse(hx509_context context, 242178825Sdfr const char *path, 243178825Sdfr hx509_request *req) 244178825Sdfr{ 245178825Sdfr CertificationRequest r; 246178825Sdfr CertificationRequestInfo *rinfo; 247178825Sdfr hx509_name subject; 248178825Sdfr size_t len, size; 249178825Sdfr void *p; 250178825Sdfr int ret; 251178825Sdfr 252178825Sdfr if (strncmp(path, "PKCS10:", 7) != 0) { 253178825Sdfr hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION, 254178825Sdfr "unsupport type in %s", path); 255178825Sdfr return HX509_UNSUPPORTED_OPERATION; 256178825Sdfr } 257178825Sdfr path += 7; 258178825Sdfr 259178825Sdfr /* XXX PEM request */ 260178825Sdfr 261233294Sstas ret = rk_undumpdata(path, &p, &len); 262178825Sdfr if (ret) { 263178825Sdfr hx509_set_error_string(context, 0, ret, "Failed to map file %s", path); 264178825Sdfr return ret; 265178825Sdfr } 266178825Sdfr 267178825Sdfr ret = decode_CertificationRequest(p, len, &r, &size); 268233294Sstas rk_xfree(p); 269178825Sdfr if (ret) { 270178825Sdfr hx509_set_error_string(context, 0, ret, "Failed to decode %s", path); 271178825Sdfr return ret; 272178825Sdfr } 273178825Sdfr 274233294Sstas ret = hx509_request_init(context, req); 275178825Sdfr if (ret) { 276178825Sdfr free_CertificationRequest(&r); 277178825Sdfr return ret; 278178825Sdfr } 279178825Sdfr 280178825Sdfr rinfo = &r.certificationRequestInfo; 281178825Sdfr 282233294Sstas ret = hx509_request_set_SubjectPublicKeyInfo(context, *req, 283178825Sdfr &rinfo->subjectPKInfo); 284178825Sdfr if (ret) { 285178825Sdfr free_CertificationRequest(&r); 286233294Sstas hx509_request_free(req); 287178825Sdfr return ret; 288178825Sdfr } 289178825Sdfr 290178825Sdfr ret = _hx509_name_from_Name(&rinfo->subject, &subject); 291178825Sdfr if (ret) { 292178825Sdfr free_CertificationRequest(&r); 293233294Sstas hx509_request_free(req); 294178825Sdfr return ret; 295178825Sdfr } 296233294Sstas ret = hx509_request_set_name(context, *req, subject); 297178825Sdfr hx509_name_free(&subject); 298178825Sdfr free_CertificationRequest(&r); 299178825Sdfr if (ret) { 300233294Sstas hx509_request_free(req); 301178825Sdfr return ret; 302178825Sdfr } 303178825Sdfr 304178825Sdfr return 0; 305178825Sdfr} 306178825Sdfr 307178825Sdfr 308178825Sdfrint 309178825Sdfr_hx509_request_print(hx509_context context, hx509_request req, FILE *f) 310178825Sdfr{ 311178825Sdfr int ret; 312178825Sdfr 313178825Sdfr if (req->name) { 314178825Sdfr char *subject; 315178825Sdfr ret = hx509_name_to_string(req->name, &subject); 316178825Sdfr if (ret) { 317178825Sdfr hx509_set_error_string(context, 0, ret, "Failed to print name"); 318178825Sdfr return ret; 319178825Sdfr } 320178825Sdfr fprintf(f, "name: %s\n", subject); 321178825Sdfr free(subject); 322178825Sdfr } 323233294Sstas 324178825Sdfr return 0; 325178825Sdfr} 326178825Sdfr 327