2 * Copyright (c) 2005 - 2006 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
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.
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
38 _hx509_map_file_os(const char *fn
, heim_octet_string
*os
, struct stat
*rsb
)
44 ret
= _hx509_map_file(fn
, &data
, &length
, rsb
);
53 _hx509_unmap_file_os(heim_octet_string
*os
)
55 _hx509_unmap_file(os
->data
, os
->length
);
59 _hx509_map_file(const char *fn
, void **data
, size_t *length
, struct stat
*rsb
)
71 fd
= open(fn
, O_RDONLY
);
75 if (fstat(fd
, &sb
) < 0) {
91 if (l
< 0 || l
!= len
) {
104 _hx509_unmap_file(void *data
, size_t len
)
110 _hx509_write_file(const char *fn
, const void *data
, size_t length
)
113 const unsigned char *p
= data
;
116 fd
= open(fn
, O_WRONLY
|O_TRUNC
|O_CREAT
, 0644);
121 sz
= write(fd
, p
, length
);
123 int saved_errno
= errno
;
130 } while (length
> 0);
143 header(FILE *f
, const char *type
, const char *str
)
145 fprintf(f
, "-----%s %s-----\n", type
, str
);
149 hx509_pem_write(hx509_context context
, const char *type
,
150 hx509_pem_header
*headers
, FILE *f
,
151 const void *data
, size_t size
)
153 const char *p
= data
;
157 #define ENCODE_LINE_LENGTH 54
159 header(f
, "BEGIN", type
);
162 fprintf(f
, "%s: %s\n%s",
163 headers
->header
, headers
->value
,
164 headers
->next
? "" : "\n");
165 headers
= headers
->next
;
172 if (length
> ENCODE_LINE_LENGTH
)
173 length
= ENCODE_LINE_LENGTH
;
175 l
= base64_encode(p
, length
, &line
);
177 hx509_set_error_string(context
, 0, ENOMEM
,
178 "malloc - out of memory");
182 fprintf(f
, "%s\n", line
);
187 header(f
, "END", type
);
197 hx509_pem_add_header(hx509_pem_header
**headers
,
198 const char *header
, const char *value
)
202 h
= calloc(1, sizeof(*h
));
205 h
->header
= strdup(header
);
206 if (h
->header
== NULL
) {
210 h
->value
= strdup(value
);
211 if (h
->value
== NULL
) {
224 hx509_pem_free_header(hx509_pem_header
*headers
)
229 headers
= headers
->next
;
241 hx509_pem_find_header(const hx509_pem_header
*h
, const char *header
)
244 if (strcmp(header
, h
->header
) == 0)
257 hx509_pem_read(hx509_context context
,
259 hx509_pem_read_func func
,
262 hx509_pem_header
*headers
= NULL
;
267 int ret
= HX509_PARSING_KEY_FAILED
;
269 enum { BEFORE
, SEARCHHEADER
, INHEADER
, INDATA
, DONE
} where
;
273 while (fgets(buf
, sizeof(buf
), f
) != NULL
) {
277 i
= strcspn(buf
, "\n");
278 if (buf
[i
] == '\n') {
283 if (buf
[i
] == '\r') {
291 if (strncmp("-----BEGIN ", buf
, 11) == 0) {
292 type
= strdup(buf
+ 11);
295 p
= strchr(type
, '-');
298 where
= SEARCHHEADER
;
302 p
= strchr(buf
, ':');
309 if (buf
[0] == '\0') {
313 p
= strchr(buf
, ':');
316 while (isspace((int)*p
))
318 ret
= hx509_pem_add_header(&headers
, buf
, p
);
326 if (strncmp("-----END ", buf
, 9) == 0) {
332 i
= base64_decode(buf
, p
);
338 data
= erealloc(data
, len
+ i
);
339 memcpy(((char *)data
) + len
, p
, i
);
348 ret
= (*func
)(context
, type
, headers
, data
, len
, ctx
);
356 hx509_pem_free_header(headers
);
363 if (where
!= BEFORE
) {
364 hx509_set_error_string(context
, 0, HX509_PARSING_KEY_FAILED
,
365 "File ends before end of PEM end tag");
366 ret
= HX509_PARSING_KEY_FAILED
;
373 hx509_pem_free_header(headers
);