source: trunk/package/px5g/src/library/x509write.c @ 20429

Last change on this file since 20429 was 20429, checked in by jow, 6 years ago

[package] add px5g (moved from LuCI trunk)

File size: 27.8 KB
Line 
1/*
2 *  X.509 certificate and private key writing
3 *
4 *  Copyright (C) 2006-2007  Pascal Vizeli <pvizeli@yahoo.de>
5 *  Modifications (C) 2009 Steven Barth <steven@midlink.org>
6 *
7 *  This library is free software; you can redistribute it and/or
8 *  modify it under the terms of the GNU Lesser General Public
9 *  License, version 2.1 as published by the Free Software Foundation.
10 *
11 *  This library is distributed in the hope that it will be useful,
12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 *  Lesser General Public License for more details.
15 *
16 *  You should have received a copy of the GNU Lesser General Public
17 *  License along with this library; if not, write to the Free Software
18 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 *  MA  02110-1301  USA
20 */
21/*
22 *  The ITU-T X.509 standard defines a certificat format for PKI.
23 *
24 *  http://www.ietf.org/rfc/rfc2459.txt
25 *  http://www.ietf.org/rfc/rfc3279.txt
26 *
27 *  ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc
28 *
29 *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
30 *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
31 *
32 *  For CRS:
33 *  http://www.faqs.org/rfcs/rfc2314.html
34 */
35#include "polarssl/config.h"
36#include "polarssl/x509.h"
37#include "polarssl/base64.h"
38#include "polarssl/sha1.h"
39
40#include <string.h>
41#include <stdlib.h>
42#include <stdio.h>
43#include <stdarg.h>
44#include <time.h>
45
46#define and &&
47#define or ||
48
49#if defined _MSC_VER && !defined snprintf
50#define snprintf _snprintf
51#endif
52
53static int x509write_realloc_node(x509_node *node, size_t larger);
54static int x509write_file(x509_node *node, char *path, int format, const char* pem_prolog, const char* pem_epilog);
55
56/*
57 * evaluate how mani octet have this integer
58 */
59static int asn1_eval_octet(unsigned int digit)
60{
61    int i, byte;
62
63    for (byte = 4, i = 24; i >= 0; i -= 8, --byte)
64        if (((digit >> i) & 0xFF) != 0)
65            return byte;
66
67    return 0;
68}
69
70/*
71 * write the asn.1 lenght form into p
72 */
73static int asn1_add_len(unsigned int size, x509_node *node)
74{
75    if (size > 127) {
76
77        /* long size */
78        int byte = asn1_eval_octet(size);
79        int i = 0;
80
81        *(node->p) = (0x80 | byte) & 0xFF;
82        ++node->p;
83
84        for (i = byte; i > 0; --i) {
85
86            *(node->p) = (size >> ((i - 1) * 8)) & 0xFF;
87            ++node->p;
88        }
89
90    } else {
91
92        /* short size */
93        *(node->p) = size & 0xFF;
94        if (size != 0)
95            ++node->p;
96    }
97
98    return 0;
99}
100
101/*
102 * write a ans.1 object into p
103 */
104static int asn1_add_obj(unsigned char *value, unsigned int size, int tag,
105        x509_node *node)
106{
107    int tl = 2;
108
109    if (tag == ASN1_BIT_STRING)
110        ++tl;
111
112    if (size > 127)
113        x509write_realloc_node(node, (size_t) size + tl +
114                asn1_eval_octet(size));
115    else
116        x509write_realloc_node(node, (size_t) size + tl);
117
118    if (node->data == NULL)
119        return 1;
120
121    /* tag */
122    *(node->p) = tag & 0xFF;
123    ++node->p;
124
125    /* len */
126    if (tag == ASN1_BIT_STRING) {
127        asn1_add_len((unsigned int) size + 1, node);
128        *(node->p) = 0x00;
129        ++node->p;
130    } else {
131        asn1_add_len((unsigned int) size, node);
132    }
133
134    /* value */
135    if (size > 0) {
136
137        memcpy(node->p, value, (size_t) size);
138        if ((node->p += size -1) != node->end)
139            return POLARSSL_ERR_X509_POINT_ERROR;
140    } else {
141        /* make nothing -> NULL */
142    }
143
144    return 0;
145}
146
147/*
148 * write a asn.1 conform integer object
149 */
150static int asn1_add_int(signed int value, x509_node *node)
151{
152    signed int i = 0, neg = 1;
153    unsigned int byte, u_val = 0, tmp_val = 0;
154
155    /* if negate? */
156    if (value < 0) {
157        neg = -1;
158        u_val = ~value;
159    } else {
160        u_val = value;
161    }
162
163    byte = asn1_eval_octet(u_val);
164    /* 0 isn't NULL */
165    if (byte == 0)
166        byte = 1;
167
168    /* ASN.1 integer is signed! */
169    if (byte < 4 and ((u_val >> ((byte -1) * 8)) & 0xFF) == 0x80)
170        byte += 1;
171
172    if (x509write_realloc_node(node, (size_t) byte + 2) != 0)
173        return 1;
174
175    /* tag */
176    *(node->p) = ASN1_INTEGER;
177    ++node->p;
178
179    /* len */
180    asn1_add_len(byte, node);
181
182    /* value */
183    for (i = byte; i > 0; --i) {
184
185        tmp_val = (u_val >> ((i - 1) * 8)) & 0xFF;
186        if (neg == 1)
187            *(node->p) = tmp_val;
188        else
189            *(node->p) = ~tmp_val;
190
191        if (i > 1)
192          ++node->p;
193    }
194
195    if (node->p != node->end)
196        return POLARSSL_ERR_X509_POINT_ERROR;
197
198    return 0;
199}
200
201/*
202 * write a asn.1 conform mpi object
203 */
204static int asn1_add_mpi(mpi *value, int tag, x509_node *node)
205{
206    size_t size = (mpi_msb(value) / 8) + 1;
207    unsigned char *buf;
208    int buf_len = (int) size, tl = 2;
209
210    if (tag == ASN1_BIT_STRING)
211        ++tl;
212
213    if (size > 127)
214        x509write_realloc_node(node, size + (size_t) tl +
215            asn1_eval_octet((unsigned int)size));
216    else
217        x509write_realloc_node(node, size + (size_t) tl);
218
219    if (node->data == NULL)
220        return 1;
221
222    buf = (unsigned char*) malloc(size);
223    if (mpi_write_binary(value, buf, buf_len) != 0)
224        return POLARSSL_ERR_MPI_BUFFER_TOO_SMALL;
225
226    /* tag */
227    *(node->p) = tag & 0xFF;
228    ++node->p;
229
230    /* len */
231    if (tag == ASN1_BIT_STRING) {
232        asn1_add_len((unsigned int) size + 1, node);
233        *(node->p) = 0x00;
234        ++node->p;
235    } else {
236        asn1_add_len((unsigned int) size, node);
237    }
238
239    /* value */
240    memcpy(node->p, buf, size);
241    free(buf);
242
243    if ((node->p += (int) size -1) != node->end)
244        return POLARSSL_ERR_X509_POINT_ERROR;
245
246    return 0;
247}
248
249/*
250 * write a node into asn.1 conform object
251 */
252static int asn1_append_tag(x509_node *node, int tag)
253{
254    int tl = 2;
255
256    x509_node tmp;
257    x509write_init_node(&tmp);
258
259    if (tag == ASN1_BIT_STRING)
260        ++tl;
261
262    if (node->len > 127)
263        x509write_realloc_node(&tmp, node->len + (size_t) tl +
264            asn1_eval_octet((unsigned int)node->len));
265    else
266        x509write_realloc_node(&tmp, node->len + (size_t) tl);
267
268    if (tmp.data == NULL) {
269        x509write_free_node(&tmp);
270        return 1;
271    }
272
273    /* tag */
274    *(tmp.p) = tag & 0xFF;
275    ++tmp.p;
276
277    /* len */
278    if (tag == ASN1_BIT_STRING) {
279        asn1_add_len((unsigned int) node->len + 1, &tmp);
280        *(tmp.p) = 0x00;
281        ++tmp.p;
282    } else {
283        asn1_add_len((unsigned int) node->len, &tmp);
284    }
285
286    /* value */
287    memcpy(tmp.p, node->data, node->len);
288
289    /* good? */
290    if ((tmp.p += (int) node->len -1) != tmp.end) {
291        x509write_free_node(&tmp);
292        return POLARSSL_ERR_X509_POINT_ERROR;
293    }
294
295    free(node->data);
296    node->data = tmp.data;
297    node->p = tmp.p;
298    node->end = tmp.end;
299    node->len = tmp.len;
300
301    return 0;
302}
303
304/*
305 * write nodes into a asn.1 object
306 */
307static int asn1_append_nodes(x509_node *node, int tag, int anz, ...)
308{
309    va_list ap;
310    size_t size = 0;
311    x509_node *tmp;
312    int count;
313
314    va_start(ap, anz);
315    count = anz;
316
317    while (count--) {
318
319        tmp = va_arg(ap, x509_node*);
320        if (tmp->data != NULL)
321            size += tmp->len;
322    }
323
324    if ( size > 127) {
325        if (x509write_realloc_node(node, size + (size_t) 2 +
326                    asn1_eval_octet(size)) != 0)
327            return 1;
328    } else {
329        if (x509write_realloc_node(node, size + (size_t) 2) != 0)
330            return 1;
331    }
332
333    /* tag */
334    *(node->p) = tag & 0xFF;
335    ++node->p;
336
337    /* len */
338    asn1_add_len(size, node);
339
340    /* value */
341    va_start(ap, anz);
342    count = anz;
343
344    while (count--) {
345
346        tmp = va_arg(ap, x509_node*);
347        if (tmp->data != NULL) {
348
349            memcpy(node->p, tmp->data, tmp->len);
350            if ((node->p += (int) tmp->len -1) != node->end)
351                ++node->p;
352        }
353    }
354
355    va_end(ap);
356    return 0;
357}
358
359/*
360 * write a ASN.1 conform object identifiere include a "tag"
361 */
362static int asn1_add_oid(x509_node *node, unsigned char *oid, size_t len,
363        int tag, int tag_val, unsigned char *value, size_t val_len)
364{
365    int ret;
366    x509_node tmp;
367
368    x509write_init_node(&tmp);
369
370    /* OBJECT IDENTIFIER */
371    if ((ret = asn1_add_obj(oid, len, ASN1_OID, &tmp)) != 0) {
372        x509write_free_node(&tmp);
373        return ret;
374    }
375
376    /* value */
377    if ((ret = asn1_add_obj(value, val_len, tag_val, &tmp)) != 0) {
378        x509write_free_node(&tmp);
379        return ret;
380    }
381
382    /* SET/SEQUENCE */
383    if ((ret = asn1_append_nodes(node, tag, 1, &tmp)) != 0) {
384        x509write_free_node(&tmp);
385        return ret;
386    }
387
388    x509write_free_node(&tmp);
389    return 0;
390}
391
392/*
393 *  utcTime        UTCTime
394 */
395static int asn1_add_date_utc(unsigned char *time, x509_node *node)
396{
397    unsigned char date[13], *sp;
398    x509_time xtime;
399    int ret;
400
401    sscanf((char*)time, "%d-%d-%d %d:%d:%d", &xtime.year, &xtime.mon,
402        &xtime.day, &xtime.hour, &xtime.min, &xtime.sec);
403
404    /* convert to YY */
405    if (xtime.year > 2000)
406        xtime.year -= 2000;
407    else
408        xtime.year -= 1900;
409
410    snprintf((char*)date, 13, "%2d%2d%2d%2d%2d%2d", xtime.year, xtime.mon, xtime.day,
411        xtime.hour, xtime.min, xtime.sec);
412
413    /* replace ' ' to '0' */
414    for (sp = date; *sp != '\0'; ++sp)
415        if (*sp == '\x20')
416            *sp = '\x30';
417
418    date[12] = 'Z';
419
420    if ((ret = asn1_add_obj(date, 13, ASN1_UTC_TIME, node)) != 0)
421        return ret;
422
423    return 0;
424}
425
426/*
427 * serialize an rsa key into DER
428 */
429
430int x509write_serialize_key(rsa_context *rsa, x509_node *node)
431{
432    int ret = 0;
433    x509write_init_node(node);
434
435    /* vers, n, e, d, p, q, dp, dq, pq */
436    if ((ret = asn1_add_int(rsa->ver, node)) != 0)
437        return ret;
438    if ((ret = asn1_add_mpi(&rsa->N, ASN1_INTEGER, node)) != 0)
439        return ret;
440    if ((ret = asn1_add_mpi(&rsa->E, ASN1_INTEGER, node)) != 0)
441        return ret;
442    if ((ret = asn1_add_mpi(&rsa->D, ASN1_INTEGER, node)) != 0)
443        return ret;
444    if ((ret = asn1_add_mpi(&rsa->P, ASN1_INTEGER, node)) != 0)
445        return ret;
446    if ((ret = asn1_add_mpi(&rsa->Q, ASN1_INTEGER, node)) != 0)
447        return ret;
448    if ((ret = asn1_add_mpi(&rsa->DP, ASN1_INTEGER, node)) != 0)
449        return ret;
450    if ((ret = asn1_add_mpi(&rsa->DQ, ASN1_INTEGER, node)) != 0)
451        return ret;
452    if ((ret = asn1_add_mpi(&rsa->QP, ASN1_INTEGER, node)) != 0)
453        return ret;
454    if ((ret = asn1_append_tag(node, ASN1_CONSTRUCTED | ASN1_SEQUENCE)) != 0)
455        return ret;
456
457    return 0;
458}
459
460/*
461 * write a der/pem encoded rsa private key into a file
462 */
463int x509write_keyfile(rsa_context *rsa, char *path, int out_flag)
464{
465    int ret = 0;
466    const char  key_beg[] = "-----BEGIN RSA PRIVATE KEY-----\n",
467                key_end[] = "-----END RSA PRIVATE KEY-----\n";
468    x509_node node;
469
470    x509write_init_node(&node);
471    if ((ret = x509write_serialize_key(rsa,&node)) != 0) {
472        x509write_free_node(&node);
473              return ret;
474    }
475
476    ret = x509write_file(&node,path,out_flag,key_beg,key_end);
477    x509write_free_node(&node);
478
479    return ret;
480}
481
482
483/*
484 * reasize the memory for node
485 */
486static int x509write_realloc_node(x509_node *node, size_t larger)
487{
488    /* init len */
489    if (node->data == NULL) {
490        node->len = 0;
491        node->data = malloc(larger);
492        if(node->data == NULL)
493            return 1;
494    } else {
495        /* realloc memory */
496        if ((node->data = realloc(node->data, node->len + larger)) == NULL)
497            return 1;
498    }
499
500    /* init pointer */
501    node->p = &node->data[node->len];
502    node->len += larger;
503    node->end = &node->data[node->len -1];
504
505    return 0;
506}
507
508/*
509 * init node
510 */
511void x509write_init_node(x509_node *node)
512{
513    memset(node, 0, sizeof(x509_node));
514}
515
516/*
517 * clean memory
518 */
519void x509write_free_node(x509_node *node)
520{
521    if (node->data != NULL)
522        free(node->data);
523    node->p = NULL;
524    node->end = NULL;
525    node->len = 0;
526}
527
528/*
529 * write a x509 certificate into file
530 */
531int x509write_crtfile(x509_raw *chain, unsigned char *path, int out_flag)
532{
533    const char  cer_beg[] = "-----BEGIN CERTIFICATE-----\n",
534                cer_end[] = "-----END CERTIFICATE-----\n";
535
536    return x509write_file(&chain->raw, (char*)path, out_flag, cer_beg, cer_end);
537}
538
539/*
540 * write a x509 certificate into file
541 */
542int x509write_csrfile(x509_raw *chain, unsigned char *path, int out_flag)
543{
544    const char  cer_beg[] = "-----BEGIN CERTIFICATE REQUEST-----\n",
545                cer_end[] = "-----END CERTIFICATE REQUEST-----\n";
546
547    return x509write_file(&chain->raw, (char*)path, out_flag, cer_beg, cer_end);
548}
549
550/*
551 * write an x509 file
552 */
553static int x509write_file(x509_node *node, char *path, int format,
554        const char* pem_prolog, const char* pem_epilog)
555{
556    FILE *ofstream = stdout;
557    int is_err = 1, buf_len, i, n;
558    unsigned char* base_buf;
559
560    if (path) {
561        if ((ofstream = fopen(path, "wb")) == NULL)
562                return 1;
563    }
564
565    switch (format) {
566        case X509_OUTPUT_DER:
567            if (fwrite(node->data, 1, node->len, ofstream)
568                != node->len)
569                is_err = -1;
570            break;
571
572        case X509_OUTPUT_PEM:
573            if (fprintf(ofstream,pem_prolog)<0) {
574                is_err = -1;
575                break;
576            }
577
578            buf_len = node->len << 1;
579            base_buf = (unsigned char*) malloc((size_t)buf_len);
580            memset(base_buf,0,buf_len);
581            if (base64_encode(base_buf, &buf_len, node->data,
582                        (int) node->len) != 0) {
583                is_err = -1;
584                break;
585            }
586
587            n=strlen((char*)base_buf);
588            for(i=0;i<n;i+=64) {
589                fprintf(ofstream,"%.64s\n",&base_buf[i]);
590            }
591
592            if (fprintf(ofstream, pem_epilog)<0) {
593                is_err = -1;
594                break;
595            }
596
597            free(base_buf);
598    }
599
600    fclose(ofstream);
601
602    if (is_err == -1)
603        return 1;
604
605    return 0;
606}
607
608
609/*
610 * add the owner public key to x509 certificate
611 */
612int x509write_add_pubkey(x509_raw *chain, rsa_context *pubkey)
613{
614    x509_node n_tmp, n_tmp2, *node;
615    int ret;
616
617    node = &chain->subpubkey;
618
619    x509write_init_node(&n_tmp);
620    x509write_init_node(&n_tmp2);
621
622    /*
623    *  RSAPublicKey ::= SEQUENCE {
624    *      modulus           INTEGER,  -- n
625    *      publicExponent    INTEGER   -- e
626    *  }
627    */
628    if ((ret = asn1_add_mpi(&pubkey->N, ASN1_INTEGER, &n_tmp)) != 0) {
629        x509write_free_node(&n_tmp);
630        x509write_free_node(&n_tmp2);
631        return ret;
632    }
633    if ((ret = asn1_add_mpi(&pubkey->E, ASN1_INTEGER, &n_tmp)) != 0) {
634        x509write_free_node(&n_tmp);
635        x509write_free_node(&n_tmp2);
636        return ret;
637    }
638    if ((ret = asn1_append_tag(&n_tmp, ASN1_CONSTRUCTED | ASN1_SEQUENCE))
639            != 0) {
640        x509write_free_node(&n_tmp);
641        x509write_free_node(&n_tmp2);
642        return ret;
643    }
644
645    /*
646     *  SubjectPublicKeyInfo  ::=  SEQUENCE  {
647     *       algorithm            AlgorithmIdentifier,
648     *       subjectPublicKey     BIT STRING }
649     */
650    if ((ret = asn1_append_tag(&n_tmp, ASN1_BIT_STRING)) != 0) {
651        x509write_free_node(&n_tmp);
652        x509write_free_node(&n_tmp2);
653       return ret;
654    }
655    if ((ret = asn1_add_oid(&n_tmp2, (unsigned char*)OID_PKCS1_RSA, 9,
656                  ASN1_CONSTRUCTED | ASN1_SEQUENCE, ASN1_NULL,
657                  (unsigned char *)"", 0)) != 0) {
658        x509write_free_node(&n_tmp);
659        x509write_free_node(&n_tmp2);
660        return ret;
661    }
662
663    if ((ret = asn1_append_nodes(node, ASN1_CONSTRUCTED | ASN1_SEQUENCE, 2,
664                   &n_tmp2, &n_tmp))) {
665        x509write_free_node(&n_tmp);
666        x509write_free_node(&n_tmp2);
667        return ret;
668    }
669
670    x509write_free_node(&n_tmp);
671    x509write_free_node(&n_tmp2);
672    return 0;
673}
674
675/*
676 *  RelativeDistinguishedName ::=
677 *    SET OF AttributeTypeAndValue
678 *
679 *  AttributeTypeAndValue ::= SEQUENCE {
680 *    type     AttributeType,
681 *    value    AttributeValue }
682 */
683static int x509write_add_name(x509_node *node, unsigned char *oid,
684        unsigned int oid_len, unsigned char *value, int len, int value_tag)
685{
686    int ret;
687    x509_node n_tmp;
688
689    x509write_init_node(&n_tmp);
690
691    if ((ret = asn1_add_oid(&n_tmp, oid, oid_len,
692                ASN1_CONSTRUCTED | ASN1_SEQUENCE, value_tag,
693                value, len))) {
694        x509write_free_node(&n_tmp);
695        return ret;
696    }
697
698    if ((asn1_append_nodes(node, ASN1_CONSTRUCTED | ASN1_SET, 1, &n_tmp))
699            != 0) {
700        x509write_free_node(&n_tmp);
701        return ret;
702    }
703
704    x509write_free_node(&n_tmp);
705    return 0;
706}
707
708/*
709 * Parse the name string and add to node
710 */
711static int x509write_parse_names(x509_node *node, unsigned char *names)
712{
713    unsigned char *sp, *begin = NULL;
714    unsigned char oid[3] = OID_X520, tag[4], *tag_sp = tag;
715    unsigned char *C = NULL, *CN = NULL, *O = NULL, *OU = NULL,
716                  *ST = NULL, *L = NULL, *R = NULL;
717    int C_len = 0, CN_len = 0, O_len = 0, OU_len = 0, ST_len = 0,
718                L_len = 0, R_len = 0;
719    int ret = 0, is_tag = 1, is_begin = -1, len = 0;
720
721
722    for (sp = names; ; ++sp) {
723
724        /* filter tag */
725        if (is_tag == 1) {
726
727            if (tag_sp == &tag[3])
728                return POLARSSL_ERR_X509_VALUE_TO_LENGTH;
729
730            /* is tag end? */
731            if (*sp == '=') {
732                is_tag = -1;
733                *tag_sp = '\0';
734                is_begin = 1;
735                /* set len 0 (reset) */
736                len = 0;
737            } else {
738                /* tag hasn't ' '! */
739                if (*sp != ' ') {
740                    *tag_sp = *sp;
741                    ++tag_sp;
742                }
743            }
744        /* filter value */
745        } else {
746
747            /* set pointer of value begin */
748            if (is_begin == 1) {
749                begin = sp;
750                is_begin = -1;
751            }
752
753            /* is value at end? */
754            if (*sp == ';' or *sp == '\0') {
755                is_tag = 1;
756
757                /* common name */
758                if (tag[0] == 'C' and tag[1] == 'N') {
759                    CN = begin;
760                    CN_len = len;
761
762                /* organization */
763                } else if (tag[0] == 'O' and tag[1] == '\0') {
764                    O = begin;
765                    O_len = len;
766
767                /* country */
768                } else if (tag[0] == 'C' and tag[1] == '\0') {
769                    C = begin;
770                    C_len = len;
771
772                /* organisation unit */
773                } else if (tag[0] == 'O' and tag[1] == 'U') {
774                    OU = begin;
775                    OU_len = len;
776
777                /* state */
778                } else if (tag[0] == 'S' and tag[1] == 'T') {
779                    ST = begin;
780                    ST_len = len;
781
782                /* locality */
783                } else if (tag[0] == 'L' and tag[1] == '\0') {
784                    L = begin;
785                    L_len = len;
786
787                /* email */
788                } else if (tag[0] == 'R' and tag[1] == '\0') {
789                    R = begin;
790                    R_len = len;
791                }
792
793                /* set tag poiner to begin */
794                tag_sp = tag;
795
796                /* is at end? */
797                if (*sp == '\0' or *(sp +1) == '\0')
798                    break;
799            } else {
800                ++len;
801            }
802        }
803
804        /* make saver */
805        if (*sp == '\0')
806          break;
807    } /* end for */
808
809    /* country */
810    if (C != NULL) {
811        oid[2] = X520_COUNTRY;
812        if ((ret = x509write_add_name(node, oid, 3, C, C_len,
813                        ASN1_PRINTABLE_STRING)) != 0)
814            return ret;
815    }
816
817    /* state */
818    if (ST != NULL) {
819        oid[2] = X520_STATE;
820        if ((ret = x509write_add_name(node, oid, 3, ST, ST_len,
821                        ASN1_PRINTABLE_STRING)) != 0)
822            return ret;
823    }
824
825    /* locality */
826    if (L != NULL) {
827        oid[2] = X520_LOCALITY;
828        if ((ret = x509write_add_name(node, oid, 3, L, L_len,
829                        ASN1_PRINTABLE_STRING)) != 0)
830            return ret;
831    }
832
833    /* organization */
834    if (O != NULL) {
835        oid[2] = X520_ORGANIZATION;
836        if ((ret = x509write_add_name(node, oid, 3, O, O_len,
837                        ASN1_PRINTABLE_STRING)) != 0)
838            return ret;
839    }
840
841    /* organisation unit */
842    if (OU != NULL) {
843        oid[2] = X520_ORG_UNIT;
844        if ((ret = x509write_add_name(node, oid, 3, OU, OU_len,
845                        ASN1_PRINTABLE_STRING)) != 0)
846            return ret;
847    }
848
849    /* common name */
850    if (CN != NULL) {
851        oid[2] = X520_COMMON_NAME;
852        if ((ret = x509write_add_name(node, oid, 3, CN, CN_len,
853                        ASN1_PRINTABLE_STRING)) != 0)
854            return ret;
855    }
856
857    /* email */
858    if (R != NULL) {
859        if ((ret = x509write_add_name(node, (unsigned char*)OID_PKCS9_EMAIL,
860                        9, R, R_len, ASN1_IA5_STRING)) != 0)
861            return ret;
862    }
863
864    if ((asn1_append_tag(node, ASN1_CONSTRUCTED | ASN1_SEQUENCE)) != 0)
865        return ret;
866
867    return 0;
868}
869
870/*
871 * Copy raw data from orginal ca to node
872 */
873static int x509write_copy_from_raw(x509_node *node, x509_buf *raw)
874{
875    if (x509write_realloc_node(node, raw->len) != 0)
876        return 1;
877
878    memcpy(node->p, raw->p, (size_t)raw->len);
879    if ((node->p += raw->len -1) != node->end)
880        return POLARSSL_ERR_X509_POINT_ERROR;
881
882    return 0;
883}
884
885/*
886 * Add the issuer
887 */
888
889int x509write_add_issuer(x509_raw *crt, unsigned char *issuer)
890{
891    return x509write_parse_names(&crt->issuer, issuer);
892}
893
894/*
895 * Add the subject
896 */
897int x509write_add_subject(x509_raw *crt, unsigned char *subject)
898{
899    return x509write_parse_names(&crt->subject, subject);
900}
901
902/*
903 * Copy issuer line from another cert to issuer
904 */
905int x509write_copy_issuer(x509_raw *crt, x509_cert *from_crt)
906{
907    return x509write_copy_from_raw(&crt->issuer, &from_crt->issuer_raw);
908}
909
910/*
911 * Copy subject line from another cert
912 */
913int x509write_copy_subject(x509_raw *crt, x509_cert *from_crt)
914{
915    return x509write_copy_from_raw(&crt->subject, &from_crt->subject_raw);
916}
917
918/*
919 * Copy subject line form antoher cert into issuer
920 */
921int x509write_copy_issuer_form_subject(x509_raw *crt,
922        x509_cert *from_crt)
923{
924    return x509write_copy_from_raw(&crt->issuer, &from_crt->subject_raw);
925}
926
927/*
928 * Copy issuer line from another cert into subject
929 */
930int x509write_copy_subject_from_issuer(x509_raw *crt,
931        x509_cert * from_crt)
932{
933    return x509write_copy_from_raw(&crt->subject, &from_crt->issuer_raw);
934}
935
936/*
937 *  Validity ::= SEQUENCE {
938 *       notBefore      Time,
939 *       notAfter       Time }
940 *
941 *  Time ::= CHOICE {
942 *       utcTime        UTCTime,
943 *       generalTime    GeneralizedTime }
944 */
945/* TODO: No handle GeneralizedTime! */
946int x509write_add_validity(x509_raw *chain, unsigned char *befor,
947        unsigned char *after)
948{
949    int ret;
950
951    x509_node *node = &chain->validity;
952
953    /* notBefore */
954    if ((ret = asn1_add_date_utc(befor, node)) != 0)
955        return ret;
956
957    /* notAfter */
958    if ((ret = asn1_add_date_utc(after, node)) != 0)
959        return ret;
960
961    if ((ret = asn1_append_tag(node, ASN1_CONSTRUCTED | ASN1_SEQUENCE)) != 0)
962        return ret;
963
964    return 0;
965}
966
967/*
968 * make hash from tbs and sign that with private key
969 */
970static int x509write_make_sign(x509_raw *chain, rsa_context *privkey)
971{
972    int ret;
973    unsigned char hash[20], *sign;
974    size_t sign_len = (size_t) mpi_size(&privkey->N);
975
976    /* make hash */
977    sha1(chain->tbs.data, chain->tbs.len, hash);
978
979    /* create sign */
980    sign = (unsigned char *) malloc(sign_len);
981    if (sign == NULL)
982        return 1;
983
984    if ((ret = rsa_pkcs1_sign(privkey, RSA_PRIVATE, RSA_SHA1, 20, hash,
985                    sign)) != 0)
986        return ret;
987
988    if ((ret = asn1_add_obj(sign, sign_len, ASN1_BIT_STRING,
989                    &chain->sign)) != 0)
990        return ret;
991
992    /*
993     *  AlgorithmIdentifier  ::=  SEQUENCE  {
994     *       algorithm               OBJECT IDENTIFIER,
995     *       parameters              ANY DEFINED BY algorithm OPTIONAL  }
996     */
997    return asn1_add_oid(&chain->signalg, (unsigned char*)OID_PKCS1_RSA_SHA, 9,
998                  ASN1_CONSTRUCTED | ASN1_SEQUENCE, ASN1_NULL,
999                  (unsigned char*)"", 0);
1000}
1001
1002/*
1003 * Create a self signed certificate
1004 */
1005int x509write_create_sign(x509_raw *chain, rsa_context *privkey)
1006{
1007    int ret, serial;
1008
1009    /*
1010     *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
1011     */
1012    if ((ret = asn1_add_int(2, &chain->version)) != 0)
1013        return ret;
1014
1015    if ((ret = asn1_append_tag(&chain->version, ASN1_CONTEXT_SPECIFIC |
1016                    ASN1_CONSTRUCTED)) != 0)
1017        return ret;
1018
1019
1020    /*
1021     *  CertificateSerialNumber  ::=  INTEGER
1022     */
1023    srand((unsigned int) time(NULL));
1024    serial = rand();
1025    if ((ret = asn1_add_int(serial, &chain->serial)) != 0)
1026        return ret;
1027
1028    /*
1029     *  AlgorithmIdentifier  ::=  SEQUENCE  {
1030     *       algorithm               OBJECT IDENTIFIER,
1031     *       parameters              ANY DEFINED BY algorithm OPTIONAL  }
1032     */
1033    if ((ret = asn1_add_oid(&chain->tbs_signalg,
1034                                (unsigned char*)OID_PKCS1_RSA_SHA, 9, ASN1_CONSTRUCTED |
1035                                ASN1_SEQUENCE, ASN1_NULL, (unsigned char*)"", 0)) != 0)
1036        return ret;
1037
1038   /*
1039    *  Create the tbs
1040    */
1041    if ((ret = asn1_append_nodes(&chain->tbs, ASN1_CONSTRUCTED |
1042                    ASN1_SEQUENCE, 7, &chain->version, &chain->serial,
1043                    &chain->tbs_signalg, &chain->issuer, &chain->validity,
1044                    &chain->subject, &chain->subpubkey)) != 0)
1045        return ret;
1046
1047    /* make signing */
1048    if ((ret = x509write_make_sign(chain, privkey)) != 0)
1049        return ret;
1050
1051    /* finishing */
1052    if ((ret = asn1_append_nodes(&chain->raw, ASN1_CONSTRUCTED |
1053                    ASN1_SEQUENCE, 3, &chain->tbs, &chain->signalg,
1054                    &chain->sign)) != 0)
1055        return ret;
1056
1057    return 0;
1058}
1059
1060int x509write_create_selfsign(x509_raw *chain, rsa_context *privkey)
1061{
1062    /*
1063     * On self signed certificate are subject and issuer the same
1064     */
1065    x509write_free_node(&chain->issuer);
1066    chain->issuer = chain->subject;
1067    return x509write_create_sign(chain, privkey);
1068}
1069
1070/*
1071 * CertificationRequestInfo ::= SEQUENCE                    {
1072 *    version                       Version,
1073 *    subject                       Name,
1074 *    subjectPublicKeyInfo          SubjectPublicKeyInfo,
1075 *    attributes                    [0] IMPLICIT Attributes }
1076 *
1077 * CertificationRequest ::=   SEQUENCE                      {
1078 *    certificationRequestInfo  CertificationRequestInfo,
1079 *    signatureAlgorithm        SignatureAlgorithmIdentifier,
1080 *    signature                 Signature                   }
1081 *
1082 * It use chain.serail for attributes!
1083 *
1084 */
1085int x509write_create_csr(x509_raw *chain, rsa_context *privkey)
1086{
1087    int ret;
1088
1089    /* version ::= INTEGER */
1090    if ((ret = asn1_add_int(0, &chain->version)) != 0)
1091        return ret;
1092
1093    /* write attributes */
1094    if ((ret = asn1_add_obj((unsigned char*)"", 0, ASN1_CONTEXT_SPECIFIC |
1095                    ASN1_CONSTRUCTED, &chain->serial)) != 0)
1096        return ret;
1097
1098    /* create CertificationRequestInfo */
1099    if ((ret = asn1_append_nodes(&chain->tbs, ASN1_CONSTRUCTED |
1100                    ASN1_SEQUENCE, 4, &chain->version, &chain->subject,
1101                    &chain->subpubkey, &chain->serial)) != 0)
1102        return ret;
1103
1104    /* make signing */
1105    if ((ret = x509write_make_sign(chain, privkey)) != 0)
1106        return ret;
1107
1108    /* finish */
1109    if ((ret = asn1_append_nodes(&chain->raw, ASN1_CONSTRUCTED | ASN1_SEQUENCE,
1110                    3, &chain->tbs, &chain->signalg, &chain->sign)) != 0)
1111        return ret;
1112
1113    return ret;
1114}
1115
1116/*
1117 * Free memory
1118 */
1119void x509write_free_raw(x509_raw *chain)
1120{
1121    x509write_free_node(&chain->raw);
1122    x509write_free_node(&chain->tbs);
1123    x509write_free_node(&chain->version);
1124    x509write_free_node(&chain->serial);
1125    x509write_free_node(&chain->tbs_signalg);
1126    x509write_free_node(&chain->issuer);
1127    x509write_free_node(&chain->validity);
1128    if (chain->subject.data != chain->issuer.data)
1129        x509write_free_node(&chain->subject);
1130    x509write_free_node(&chain->subpubkey);
1131    x509write_free_node(&chain->signalg);
1132    x509write_free_node(&chain->sign);
1133}
1134
1135void x509write_init_raw(x509_raw *chain)
1136{
1137    memset((void *) chain, 0, sizeof(x509_raw));
1138}
1139
Note: See TracBrowser for help on using the repository browser.