1*8ccd4a63SDavid du Colombier #include <u.h>
2*8ccd4a63SDavid du Colombier #include <libc.h>
3*8ccd4a63SDavid du Colombier #include <mp.h>
4*8ccd4a63SDavid du Colombier #include <libsec.h>
5*8ccd4a63SDavid du Colombier
6*8ccd4a63SDavid du Colombier #define STRLEN(s) (sizeof(s)-1)
7*8ccd4a63SDavid du Colombier
8*8ccd4a63SDavid du Colombier uchar*
decodepem(char * s,char * type,int * len)9*8ccd4a63SDavid du Colombier decodepem(char *s, char *type, int *len)
10*8ccd4a63SDavid du Colombier {
11*8ccd4a63SDavid du Colombier uchar *d;
12*8ccd4a63SDavid du Colombier char *t, *e, *tt;
13*8ccd4a63SDavid du Colombier int n;
14*8ccd4a63SDavid du Colombier
15*8ccd4a63SDavid du Colombier /*
16*8ccd4a63SDavid du Colombier * find the correct section of the file, stripping garbage at the beginning and end.
17*8ccd4a63SDavid du Colombier * the data is delimited by -----BEGIN <type>-----\n and -----END <type>-----\n
18*8ccd4a63SDavid du Colombier */
19*8ccd4a63SDavid du Colombier n = strlen(type);
20*8ccd4a63SDavid du Colombier e = strchr(s, '\0');
21*8ccd4a63SDavid du Colombier for(t = s; t != nil && t < e; ){
22*8ccd4a63SDavid du Colombier tt = t;
23*8ccd4a63SDavid du Colombier t = strchr(tt, '\n');
24*8ccd4a63SDavid du Colombier if(t != nil)
25*8ccd4a63SDavid du Colombier t++;
26*8ccd4a63SDavid du Colombier if(strncmp(tt, "-----BEGIN ", STRLEN("-----BEGIN ")) == 0
27*8ccd4a63SDavid du Colombier && strncmp(&tt[STRLEN("-----BEGIN ")], type, n) == 0
28*8ccd4a63SDavid du Colombier && strncmp(&tt[STRLEN("-----BEGIN ")+n], "-----\n", STRLEN("-----\n")) == 0)
29*8ccd4a63SDavid du Colombier break;
30*8ccd4a63SDavid du Colombier }
31*8ccd4a63SDavid du Colombier for(tt = t; tt != nil && tt < e; tt++){
32*8ccd4a63SDavid du Colombier if(strncmp(tt, "-----END ", STRLEN("-----END ")) == 0
33*8ccd4a63SDavid du Colombier && strncmp(&tt[STRLEN("-----END ")], type, n) == 0
34*8ccd4a63SDavid du Colombier && strncmp(&tt[STRLEN("-----END ")+n], "-----\n", STRLEN("-----\n")) == 0)
35*8ccd4a63SDavid du Colombier break;
36*8ccd4a63SDavid du Colombier tt = strchr(tt, '\n');
37*8ccd4a63SDavid du Colombier if(tt == nil)
38*8ccd4a63SDavid du Colombier break;
39*8ccd4a63SDavid du Colombier }
40*8ccd4a63SDavid du Colombier if(tt == nil || tt == e){
41*8ccd4a63SDavid du Colombier werrstr("incorrect .pem file format: bad header or trailer");
42*8ccd4a63SDavid du Colombier return nil;
43*8ccd4a63SDavid du Colombier }
44*8ccd4a63SDavid du Colombier
45*8ccd4a63SDavid du Colombier n = ((tt - t) * 6 + 7) / 8;
46*8ccd4a63SDavid du Colombier d = malloc(n);
47*8ccd4a63SDavid du Colombier if(d == nil){
48*8ccd4a63SDavid du Colombier werrstr("out of memory");
49*8ccd4a63SDavid du Colombier return nil;
50*8ccd4a63SDavid du Colombier }
51*8ccd4a63SDavid du Colombier n = dec64(d, n, t, tt - t);
52*8ccd4a63SDavid du Colombier if(n < 0){
53*8ccd4a63SDavid du Colombier free(d);
54*8ccd4a63SDavid du Colombier werrstr("incorrect .pem file format: bad base64 encoded data");
55*8ccd4a63SDavid du Colombier return nil;
56*8ccd4a63SDavid du Colombier }
57*8ccd4a63SDavid du Colombier *len = n;
58*8ccd4a63SDavid du Colombier return d;
59*8ccd4a63SDavid du Colombier }
60