Initial commit to the repository
[deb_shairplay.git] / src / rsapem.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <ctype.h>
5
6 #include "rsapem.h"
7 #include "base64.h"
8
9 #define RSAPRIVHEADER "-----BEGIN RSA PRIVATE KEY-----"
10 #define RSAPRIVFOOTER "-----END RSA PRIVATE KEY-----"
11
12 struct rsapem_s {
13 unsigned char *data;
14 unsigned int datalen;
15 unsigned int datapos;
16 };
17
18 rsapem_t *
19 rsapem_init(const char *pemstr)
20 {
21 rsapem_t *rsapem=NULL;
22 const char *header;
23 const char *footer;
24 base64_t *b64dec;
25 unsigned char *data;
26 int datalen;
27
28 header = strstr(pemstr, RSAPRIVHEADER);
29 footer = strstr(pemstr, RSAPRIVFOOTER);
30 if (!header || !footer) {
31 return NULL;
32 }
33
34
35 /* Base64 decode the whole input excluding header and footer */
36 b64dec = base64_init(NULL, 0, 1);
37 datalen = base64_decode(b64dec, &data, pemstr+sizeof(RSAPRIVHEADER),
38 (footer-header)-sizeof(RSAPRIVHEADER));
39 base64_destroy(b64dec);
40 b64dec = NULL;
41
42 if (datalen < 0) {
43 return NULL;
44 }
45
46 #ifdef RSAPEM_DEBUG
47 {
48 int i;
49 printf("Decoded output:\n");
50 for (i=0; i<datalen; i++) {
51 printf("%02x", data[i]);
52 }
53 printf("\n");
54 }
55 #endif
56
57 /* Check that first 4 bytes are all valid */
58 if (datalen < 4 || data[0] != 0x30 || data[1] != 0x82) {
59 free(data);
60 return NULL;
61 } else if (((data[2] << 8) | data[3]) != datalen-4) {
62 free(data);
63 return NULL;
64 }
65
66 rsapem = calloc(1, sizeof(rsapem_t));
67 if (!rsapem) {
68 free(data);
69 return NULL;
70 }
71
72 /* Initialize the data */
73 rsapem->data = data;
74 rsapem->datalen = datalen;
75 rsapem->datapos = 4;
76
77 data = NULL;
78 datalen = rsapem_read_vector(rsapem, &data);
79 if (datalen != 1 && data[0] != 0x00) {
80 free(data);
81 rsapem_destroy(rsapem);
82 return NULL;
83 }
84 free(data);
85 return rsapem;
86 }
87
88 void
89 rsapem_destroy(rsapem_t *rsapem)
90 {
91 if (rsapem) {
92 free(rsapem->data);
93 free(rsapem);
94 }
95 }
96
97 int
98 rsapem_read_vector(rsapem_t *rsapem, unsigned char **data)
99 {
100 unsigned int length;
101 unsigned char *ptr;
102
103 if (rsapem->datalen-rsapem->datapos < 2) {
104 return -1;
105 }
106 if (rsapem->data[rsapem->datapos] != 0x02) {
107 return -2;
108 }
109
110 /* Read vector length */
111 length = rsapem->data[rsapem->datapos+1];
112 if (length <= 0x80) {
113 rsapem->datapos += 2;
114 } else if (length == 0x81) {
115 if (rsapem->datalen-rsapem->datapos < 3) {
116 return -3;
117 }
118 length = rsapem->data[rsapem->datapos+2];
119 rsapem->datapos += 3;
120 } else if (length == 0x82) {
121 if (rsapem->datalen-rsapem->datapos < 4) {
122 return -3;
123 }
124 length = (rsapem->data[rsapem->datapos+2] << 8) |
125 rsapem->data[rsapem->datapos+3];
126 rsapem->datapos += 4;
127 } else {
128 return -3;
129 }
130
131 /* Check that we have enough data available */
132 if (rsapem->datalen-rsapem->datapos < length) {
133 return -4;
134 }
135
136 /* Allocate data buffer and read bytes */
137 ptr = malloc(length);
138 if (!ptr) {
139 return -5;
140 }
141 memcpy(ptr, rsapem->data+rsapem->datapos, length);
142 rsapem->datapos += length;
143
144 /* Return buffer and length */
145 *data = ptr;
146 return length;
147 }
148