@@ -18,13 +18,39 @@ extern const struct blockcipher_info pem_dek_infos[];
18
18
extern const unsigned long pem_dek_infos_num ;
19
19
20
20
#ifndef LTC_NO_FILE
21
- int pem_get_char_from_file (struct get_char * g )
21
+ static int s_pem_get_char_from_file (struct get_char * g )
22
22
{
23
- return getc (g -> data .f );
23
+ return getc (g -> data .f . f );
24
24
}
25
+
26
+ static int s_pem_get_char_reset_file (struct get_char * g )
27
+ {
28
+ if (g -> data .f .original_pos == -1 )
29
+ return -1 ;
30
+ return fseek (g -> data .f .f , g -> data .f .original_pos , SEEK_SET );
31
+ }
32
+
33
+ static unsigned long s_pem_get_char_len_file (struct get_char * g )
34
+ {
35
+ FILE * f = g -> data .f .f ;
36
+ long len , cur_pos = ftell (f );
37
+ if (cur_pos != -1 ) {
38
+ fseek (f , 0 , SEEK_END );
39
+ len = ftell (f );
40
+ fseek (f , cur_pos , SEEK_SET );
41
+ return len - cur_pos ;
42
+ }
43
+ return LTC_PEM_READ_BUFSIZE * 2 ;
44
+ }
45
+
46
+ const struct get_char_api get_char_filehandle_api = {
47
+ .get = s_pem_get_char_from_file ,
48
+ .reset = s_pem_get_char_reset_file ,
49
+ .len = s_pem_get_char_len_file ,
50
+ };
25
51
#endif /* LTC_NO_FILE */
26
52
27
- int pem_get_char_from_buf (struct get_char * g )
53
+ static int s_pem_get_char_from_buf (struct get_char * g )
28
54
{
29
55
int ret ;
30
56
if (g -> data .buf .work == g -> data .buf .end ) {
@@ -35,6 +61,23 @@ int pem_get_char_from_buf(struct get_char *g)
35
61
return ret ;
36
62
}
37
63
64
+ static int s_pem_get_char_reset (struct get_char * g )
65
+ {
66
+ g -> data .buf .work = g -> data .buf .start ;
67
+ return 0 ;
68
+ }
69
+
70
+ static unsigned long s_pem_get_char_len (struct get_char * g )
71
+ {
72
+ return g -> data .buf .end - g -> data .buf .start - 1 ;
73
+ }
74
+
75
+ const struct get_char_api get_char_buffer_api = {
76
+ .get = s_pem_get_char_from_buf ,
77
+ .reset = s_pem_get_char_reset ,
78
+ .len = s_pem_get_char_len ,
79
+ };
80
+
38
81
static void s_unget_line (char * buf , unsigned long buflen , struct get_char * g )
39
82
{
40
83
if (buflen > sizeof (g -> unget_buf_ ))
@@ -81,7 +124,7 @@ static char* s_get_line_i(char *buf, unsigned long *buflen, struct get_char *g,
81
124
while (blen < * buflen || search_for_start ) {
82
125
wr = blen < * buflen ? blen : * buflen - 1 ;
83
126
c_ = g -> prev_get ;
84
- g -> prev_get = g -> get (g );
127
+ g -> prev_get = g -> api . get (g );
85
128
if (g -> prev_get == '\n' ) {
86
129
buf [wr ] = '\0' ;
87
130
if (c_ == '\r' ) {
@@ -190,11 +233,11 @@ static int s_pem_decode_headers(struct pem_headers *hdr, struct get_char *g)
190
233
return CRYPT_OK ;
191
234
}
192
235
193
- int pem_read (void * asn1_cert , unsigned long * asn1_len , struct pem_headers * hdr , struct get_char * g )
236
+ static int s_pem_read (void * buf , unsigned long * len , struct pem_headers * hdr , struct get_char * g )
194
237
{
195
- char buf [LTC_PEM_DECODE_BUFSZ ];
196
- char * wpem = asn1_cert ;
197
- char * end = wpem + * asn1_len ;
238
+ char line [LTC_PEM_DECODE_BUFSZ ];
239
+ char * wpem = buf ;
240
+ char * end = wpem + * len ;
198
241
const char pem_start [] = "----" ;
199
242
unsigned long slen , linelen ;
200
243
int err , hdr_ok = 0 ;
@@ -203,18 +246,18 @@ int pem_read(void *asn1_cert, unsigned long *asn1_len, struct pem_headers *hdr,
203
246
204
247
g -> prev_get = 0 ;
205
248
do {
206
- linelen = sizeof (buf );
207
- if (s_get_first_line (buf , & linelen , g ) == NULL ) {
249
+ linelen = sizeof (line );
250
+ if (s_get_first_line (line , & linelen , g ) == NULL ) {
208
251
if (g -> prev_get == -1 )
209
252
return CRYPT_NOP ;
210
253
else
211
254
return CRYPT_INVALID_PACKET ;
212
255
}
213
256
if (linelen < sizeof (pem_start ) - 1 )
214
257
continue ;
215
- } while (XMEMCMP (buf , pem_start , sizeof (pem_start ) - 1 ) != 0 );
216
- if (hdr -> id -> start .len != linelen || XMEMCMP (buf , hdr -> id -> start .p , hdr -> id -> start .len )) {
217
- s_unget_line (buf , linelen , g );
258
+ } while (XMEMCMP (line , pem_start , sizeof (pem_start ) - 1 ) != 0 );
259
+ if (hdr -> id -> start .len != linelen || XMEMCMP (line , hdr -> id -> start .p , hdr -> id -> start .len )) {
260
+ s_unget_line (line , linelen , g );
218
261
return CRYPT_UNKNOWN_PEM ;
219
262
}
220
263
@@ -223,9 +266,9 @@ int pem_read(void *asn1_cert, unsigned long *asn1_len, struct pem_headers *hdr,
223
266
return err ;
224
267
225
268
/* Read the base64 encoded part of the PEM */
226
- slen = sizeof (buf );
227
- while (s_get_line (buf , & slen , g )) {
228
- if (slen == hdr -> id -> end .len && !XMEMCMP (buf , hdr -> id -> end .p , slen )) {
269
+ slen = sizeof (line );
270
+ while (s_get_line (line , & slen , g )) {
271
+ if (slen == hdr -> id -> end .len && !XMEMCMP (line , hdr -> id -> end .p , slen )) {
229
272
hdr_ok = 1 ;
230
273
break ;
231
274
}
@@ -235,12 +278,12 @@ int pem_read(void *asn1_cert, unsigned long *asn1_len, struct pem_headers *hdr,
235
278
empty_lines ++ ;
236
279
}
237
280
if (!would_overflow && s_fits_buf (wpem , slen , end )) {
238
- XMEMCPY (wpem , buf , slen );
281
+ XMEMCPY (wpem , line , slen );
239
282
} else {
240
283
would_overflow = 1 ;
241
284
}
242
285
wpem += slen ;
243
- slen = sizeof (buf );
286
+ slen = sizeof (line );
244
287
}
245
288
if (!hdr_ok )
246
289
return CRYPT_INVALID_PACKET ;
@@ -249,19 +292,47 @@ int pem_read(void *asn1_cert, unsigned long *asn1_len, struct pem_headers *hdr,
249
292
/* NUL termination */
250
293
wpem ++ ;
251
294
/* prevent a wrap-around */
252
- if (wpem < (char * )asn1_cert )
295
+ if (wpem < (char * )buf )
253
296
return CRYPT_OVERFLOW ;
254
- * asn1_len = wpem - (char * )asn1_cert ;
297
+ * len = wpem - (char * )buf ;
255
298
return CRYPT_BUFFER_OVERFLOW ;
256
299
}
257
300
258
- * asn1_len = wpem - (char * )asn1_cert ;
301
+ * len = wpem - (char * )buf ;
259
302
* wpem ++ = '\0' ;
260
303
261
- if ((err = base64_strict_decode (asn1_cert , * asn1_len , asn1_cert , asn1_len )) != CRYPT_OK ) {
304
+ if ((err = base64_strict_decode (buf , * len , buf , len )) != CRYPT_OK ) {
262
305
return err ;
263
306
}
264
307
return CRYPT_OK ;
265
308
}
266
309
310
+ int pem_read (void * * dest , unsigned long * len , struct pem_headers * hdr , struct get_char * g )
311
+ {
312
+ int err , once = 0 ;
313
+ void * work = NULL , * work_ ;
314
+ unsigned long work_len = g -> api .len (g );
315
+ retry :
316
+ work_ = XREALLOC (work , work_len );
317
+ if (work_ == NULL ) {
318
+ goto error_out ;
319
+ }
320
+ work = work_ ;
321
+ once ++ ;
322
+ if ((err = s_pem_read (work , & work_len , hdr , g )) == CRYPT_BUFFER_OVERFLOW
323
+ && once == 1 ) {
324
+ if (g -> api .reset (g ) != -1 ) {
325
+ goto retry ;
326
+ }
327
+ }
328
+ if (err != CRYPT_OK ) {
329
+ error_out :
330
+ XFREE (work );
331
+ work = NULL ;
332
+ }
333
+ * dest = work ;
334
+ * len = work_len ;
335
+ return err ;
336
+ }
337
+
267
338
#endif /* LTC_PEM */
0 commit comments