@@ -18,13 +18,39 @@ extern const struct blockcipher_info pem_dek_infos[];
1818extern const unsigned long pem_dek_infos_num ;
1919
2020#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 )
2222{
23- return getc (g -> data .f );
23+ return getc (g -> data .f . f );
2424}
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+ };
2551#endif /* LTC_NO_FILE */
2652
27- int pem_get_char_from_buf (struct get_char * g )
53+ static int s_pem_get_char_from_buf (struct get_char * g )
2854{
2955 int ret ;
3056 if (g -> data .buf .work == g -> data .buf .end ) {
@@ -35,6 +61,23 @@ int pem_get_char_from_buf(struct get_char *g)
3561 return ret ;
3662}
3763
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+
3881static void s_unget_line (char * buf , unsigned long buflen , struct get_char * g )
3982{
4083 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,
81124 while (blen < * buflen || search_for_start ) {
82125 wr = blen < * buflen ? blen : * buflen - 1 ;
83126 c_ = g -> prev_get ;
84- g -> prev_get = g -> get (g );
127+ g -> prev_get = g -> api . get (g );
85128 if (g -> prev_get == '\n' ) {
86129 buf [wr ] = '\0' ;
87130 if (c_ == '\r' ) {
@@ -190,11 +233,11 @@ static int s_pem_decode_headers(struct pem_headers *hdr, struct get_char *g)
190233 return CRYPT_OK ;
191234}
192235
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 )
194237{
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 ;
198241 const char pem_start [] = "----" ;
199242 unsigned long slen , linelen ;
200243 int err , hdr_ok = 0 ;
@@ -203,18 +246,18 @@ int pem_read(void *asn1_cert, unsigned long *asn1_len, struct pem_headers *hdr,
203246
204247 g -> prev_get = 0 ;
205248 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 ) {
208251 if (g -> prev_get == -1 )
209252 return CRYPT_NOP ;
210253 else
211254 return CRYPT_INVALID_PACKET ;
212255 }
213256 if (linelen < sizeof (pem_start ) - 1 )
214257 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 );
218261 return CRYPT_UNKNOWN_PEM ;
219262 }
220263
@@ -223,9 +266,9 @@ int pem_read(void *asn1_cert, unsigned long *asn1_len, struct pem_headers *hdr,
223266 return err ;
224267
225268 /* 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 )) {
229272 hdr_ok = 1 ;
230273 break ;
231274 }
@@ -235,12 +278,12 @@ int pem_read(void *asn1_cert, unsigned long *asn1_len, struct pem_headers *hdr,
235278 empty_lines ++ ;
236279 }
237280 if (!would_overflow && s_fits_buf (wpem , slen , end )) {
238- XMEMCPY (wpem , buf , slen );
281+ XMEMCPY (wpem , line , slen );
239282 } else {
240283 would_overflow = 1 ;
241284 }
242285 wpem += slen ;
243- slen = sizeof (buf );
286+ slen = sizeof (line );
244287 }
245288 if (!hdr_ok )
246289 return CRYPT_INVALID_PACKET ;
@@ -249,19 +292,47 @@ int pem_read(void *asn1_cert, unsigned long *asn1_len, struct pem_headers *hdr,
249292 /* NUL termination */
250293 wpem ++ ;
251294 /* prevent a wrap-around */
252- if (wpem < (char * )asn1_cert )
295+ if (wpem < (char * )buf )
253296 return CRYPT_OVERFLOW ;
254- * asn1_len = wpem - (char * )asn1_cert ;
297+ * len = wpem - (char * )buf ;
255298 return CRYPT_BUFFER_OVERFLOW ;
256299 }
257300
258- * asn1_len = wpem - (char * )asn1_cert ;
301+ * len = wpem - (char * )buf ;
259302 * wpem ++ = '\0' ;
260303
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 ) {
262305 return err ;
263306 }
264307 return CRYPT_OK ;
265308}
266309
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+
267338#endif /* LTC_PEM */
0 commit comments