1 #include <u.h> 2 #include <libc.h> 3 #include <mp.h> 4 #include <libsec.h> 5 6 #define STRLEN(s) (sizeof(s)-1) 7 8 uchar* 9 decodePEM(char *s, char *type, int *len, char **new_s) 10 { 11 uchar *d; 12 char *t, *e, *tt; 13 int n; 14 15 *len = 0; 16 17 /* 18 * find the correct section of the file, stripping garbage at the beginning and end. 19 * the data is delimited by -----BEGIN <type>-----\n and -----END <type>-----\n 20 */ 21 n = strlen(type); 22 e = strchr(s, '\0'); 23 for(t = s; t != nil && t < e; ){ 24 tt = t; 25 t = strchr(tt, '\n'); 26 if(t != nil) 27 t++; 28 if(strncmp(tt, "-----BEGIN ", STRLEN("-----BEGIN ")) == 0 29 && strncmp(&tt[STRLEN("-----BEGIN ")], type, n) == 0 30 && strncmp(&tt[STRLEN("-----BEGIN ")+n], "-----\n", STRLEN("-----\n")) == 0) 31 break; 32 } 33 for(tt = t; tt != nil && tt < e; tt++){ 34 if(strncmp(tt, "-----END ", STRLEN("-----END ")) == 0 35 && strncmp(&tt[STRLEN("-----END ")], type, n) == 0 36 && strncmp(&tt[STRLEN("-----END ")+n], "-----\n", STRLEN("-----\n")) == 0) 37 break; 38 tt = strchr(tt, '\n'); 39 if(tt == nil) 40 break; 41 } 42 if(tt == nil || tt == e){ 43 werrstr("incorrect .pem file format: bad header or trailer"); 44 return nil; 45 } 46 47 if(new_s) 48 *new_s = tt+1; 49 n = ((tt - t) * 6 + 7) / 8; 50 d = malloc(n); 51 if(d == nil){ 52 werrstr("out of memory"); 53 return nil; 54 } 55 n = dec64(d, n, t, tt - t); 56 if(n < 0){ 57 free(d); 58 werrstr("incorrect .pem file format: bad base64 encoded data"); 59 return nil; 60 } 61 *len = n; 62 return d; 63 } 64 65 PEMChain* 66 decodepemchain(char *s, char *type) 67 { 68 PEMChain *first = nil, *last = nil, *chp; 69 uchar *d; 70 char *e; 71 int n; 72 73 e = strchr(s, '\0'); 74 while (s < e) { 75 d = decodePEM(s, type, &n, &s); 76 if(d == nil) 77 break; 78 chp = malloc(sizeof(PEMChain)); 79 chp->next = nil; 80 chp->pem = d; 81 chp->pemlen = n; 82 if (first == nil) 83 first = chp; 84 else 85 last->next = chp; 86 last = chp; 87 } 88 return first; 89 } 90