root/source4/heimdal/lib/hx509/req.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. _hx509_request_init
  2. _hx509_request_free
  3. _hx509_request_set_name
  4. _hx509_request_get_name
  5. _hx509_request_set_SubjectPublicKeyInfo
  6. _hx509_request_get_SubjectPublicKeyInfo
  7. _hx509_request_add_eku
  8. _hx509_request_add_dns_name
  9. _hx509_request_add_email
  10. _hx509_request_to_pkcs10
  11. _hx509_request_parse
  12. _hx509_request_print

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

/* [<][>][^][v][top][bottom][index][help] */