@@ -17,14 +17,98 @@ extern const struct str pem_dek_info_start;
1717extern const struct blockcipher_info pem_dek_infos [];
1818extern const unsigned long pem_dek_infos_num ;
1919
20+ static LTC_INLINE unsigned long s_bufp_alloc_len (struct bufp * buf )
21+ {
22+ if (buf -> start == NULL || buf -> end == NULL )
23+ return 0 ;
24+ return buf -> end - buf -> start - 1 ;
25+ }
26+
27+ static LTC_INLINE unsigned long s_bufp_used_len (struct bufp * buf )
28+ {
29+ if (buf -> start == NULL || buf -> end == NULL )
30+ return 0 ;
31+ return buf -> work - buf -> start ;
32+ }
33+
34+ static LTC_INLINE int s_bufp_grow (struct bufp * buf )
35+ {
36+ int err = CRYPT_OK ;
37+ void * ret ;
38+ unsigned long alloc_len = s_bufp_alloc_len (buf ), realloc_len ;
39+ unsigned long work_offset = s_bufp_used_len (buf );
40+ if (alloc_len == 0 )
41+ realloc_len = LTC_PEM_READ_BUFSIZE ;
42+ else
43+ realloc_len = alloc_len * 2 ;
44+ if (realloc_len < alloc_len )
45+ return CRYPT_OVERFLOW ;
46+ ret = XREALLOC (buf -> start , realloc_len );
47+ if (ret == NULL ) {
48+ err = CRYPT_MEM ;
49+ } else {
50+ UPDATE_BUFP ((* buf ), ret , work_offset , realloc_len );
51+ }
52+ return err ;
53+ }
54+
55+ static LTC_INLINE int s_bufp_fits (struct bufp * buf , unsigned long to_write )
56+ {
57+ char * d = buf -> work ;
58+ char * e = buf -> end ;
59+ char * w = d + to_write ;
60+ if (d == NULL || w < d || w > e )
61+ return 0 ;
62+ return 1 ;
63+ }
64+
65+ static LTC_INLINE int s_bufp_add (struct bufp * buf , const void * src , unsigned long len )
66+ {
67+ int err ;
68+ if (!s_bufp_fits (buf , len )) {
69+ if ((err = s_bufp_grow (buf )) != CRYPT_OK ) {
70+ return err ;
71+ }
72+ }
73+ XMEMCPY (buf -> work , src , len );
74+ buf -> work += len ;
75+ return CRYPT_OK ;
76+ }
77+
2078#ifndef LTC_NO_FILE
21- int pem_get_char_from_file (struct get_char * g )
79+ static int s_pem_get_char_from_file (struct get_char * g )
80+ {
81+ return getc (g -> data .f .f );
82+ }
83+
84+ static int s_pem_get_char_reset_file (struct get_char * g )
2285{
23- return getc (g -> data .f );
86+ if (g -> data .f .original_pos == -1 )
87+ return -1 ;
88+ return fseek (g -> data .f .f , g -> data .f .original_pos , SEEK_SET );
2489}
90+
91+ static unsigned long s_pem_get_char_len_file (struct get_char * g )
92+ {
93+ FILE * f = g -> data .f .f ;
94+ long len , cur_pos = ftell (f );
95+ if (cur_pos != -1 ) {
96+ fseek (f , 0 , SEEK_END );
97+ len = ftell (f );
98+ fseek (f , cur_pos , SEEK_SET );
99+ return len - cur_pos ;
100+ }
101+ return LTC_PEM_READ_BUFSIZE * 2 ;
102+ }
103+
104+ const struct get_char_api get_char_filehandle_api = {
105+ .get = s_pem_get_char_from_file ,
106+ .reset = s_pem_get_char_reset_file ,
107+ .len = s_pem_get_char_len_file ,
108+ };
25109#endif /* LTC_NO_FILE */
26110
27- int pem_get_char_from_buf (struct get_char * g )
111+ static int s_pem_get_char_from_buf (struct get_char * g )
28112{
29113 int ret ;
30114 if (g -> data .buf .work == g -> data .buf .end ) {
@@ -35,6 +119,25 @@ int pem_get_char_from_buf(struct get_char *g)
35119 return ret ;
36120}
37121
122+ static int s_pem_get_char_reset (struct get_char * g )
123+ {
124+ g -> data .buf .work = g -> data .buf .start ;
125+ return 0 ;
126+ }
127+
128+
129+
130+ static unsigned long s_pem_get_char_len (struct get_char * g )
131+ {
132+ return s_bufp_alloc_len (& g -> data .buf );
133+ }
134+
135+ const struct get_char_api get_char_buffer_api = {
136+ .get = s_pem_get_char_from_buf ,
137+ .reset = s_pem_get_char_reset ,
138+ .len = s_pem_get_char_len ,
139+ };
140+
38141static void s_unget_line (char * buf , unsigned long buflen , struct get_char * g )
39142{
40143 if (buflen > sizeof (g -> unget_buf_ ))
@@ -81,7 +184,7 @@ static char* s_get_line_i(char *buf, unsigned long *buflen, struct get_char *g,
81184 while (blen < * buflen || search_for_start ) {
82185 wr = blen < * buflen ? blen : * buflen - 1 ;
83186 c_ = g -> prev_get ;
84- g -> prev_get = g -> get (g );
187+ g -> prev_get = g -> api . get (g );
85188 if (g -> prev_get == '\n' ) {
86189 buf [wr ] = '\0' ;
87190 if (c_ == '\r' ) {
@@ -103,26 +206,16 @@ static char* s_get_line_i(char *buf, unsigned long *buflen, struct get_char *g,
103206 return NULL ;
104207}
105208
106- LTC_INLINE static char * s_get_first_line (char * buf , unsigned long * buflen , struct get_char * g )
209+ static LTC_INLINE char * s_get_first_line (char * buf , unsigned long * buflen , struct get_char * g )
107210{
108211 return s_get_line_i (buf , buflen , g , 1 );
109212}
110213
111- LTC_INLINE static char * s_get_line (char * buf , unsigned long * buflen , struct get_char * g )
214+ static LTC_INLINE char * s_get_line (char * buf , unsigned long * buflen , struct get_char * g )
112215{
113216 return s_get_line_i (buf , buflen , g , 0 );
114217}
115218
116- static LTC_INLINE int s_fits_buf (void * dest , unsigned long to_write , void * end )
117- {
118- unsigned char * d = dest ;
119- unsigned char * e = end ;
120- unsigned char * w = d + to_write ;
121- if (w < d || w > e )
122- return 0 ;
123- return 1 ;
124- }
125-
126219static int s_pem_decode_headers (struct pem_headers * hdr , struct get_char * g )
127220{
128221 char buf [LTC_PEM_DECODE_BUFSZ ], * alg_start ;
@@ -190,31 +283,29 @@ static int s_pem_decode_headers(struct pem_headers *hdr, struct get_char *g)
190283 return CRYPT_OK ;
191284}
192285
193- int pem_read (void * asn1_cert , unsigned long * asn1_len , struct pem_headers * hdr , struct get_char * g )
286+ int pem_read (void * * dest , unsigned long * len , struct pem_headers * hdr , struct get_char * g )
194287{
195- char buf [LTC_PEM_DECODE_BUFSZ ];
196- char * wpem = asn1_cert ;
197- char * end = wpem + * asn1_len ;
288+ char line [LTC_PEM_DECODE_BUFSZ ];
289+ struct bufp b_ = {0 }, * b = & b_ ;
198290 const char pem_start [] = "----" ;
199291 unsigned long slen , linelen ;
200292 int err , hdr_ok = 0 ;
201- int would_overflow = 0 ;
202293 unsigned char empty_lines = 0 ;
203294
204295 g -> prev_get = 0 ;
205296 do {
206- linelen = sizeof (buf );
207- if (s_get_first_line (buf , & linelen , g ) == NULL ) {
297+ linelen = sizeof (line );
298+ if (s_get_first_line (line , & linelen , g ) == NULL ) {
208299 if (g -> prev_get == -1 )
209300 return CRYPT_NOP ;
210301 else
211302 return CRYPT_INVALID_PACKET ;
212303 }
213304 if (linelen < sizeof (pem_start ) - 1 )
214305 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 );
306+ } while (XMEMCMP (line , pem_start , sizeof (pem_start ) - 1 ) != 0 );
307+ if (hdr -> id -> start .len != linelen || XMEMCMP (line , hdr -> id -> start .p , hdr -> id -> start .len )) {
308+ s_unget_line (line , linelen , g );
218309 return CRYPT_UNKNOWN_PEM ;
219310 }
220311
@@ -223,9 +314,9 @@ int pem_read(void *asn1_cert, unsigned long *asn1_len, struct pem_headers *hdr,
223314 return err ;
224315
225316 /* 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 )) {
317+ slen = sizeof (line );
318+ while (s_get_line (line , & slen , g )) {
319+ if (slen == hdr -> id -> end .len && !XMEMCMP (line , hdr -> id -> end .p , slen )) {
229320 hdr_ok = 1 ;
230321 break ;
231322 }
@@ -234,34 +325,25 @@ int pem_read(void *asn1_cert, unsigned long *asn1_len, struct pem_headers *hdr,
234325 break ;
235326 empty_lines ++ ;
236327 }
237- if (!would_overflow && s_fits_buf (wpem , slen , end )) {
238- XMEMCPY (wpem , buf , slen );
239- } else {
240- would_overflow = 1 ;
328+ if ((err = s_bufp_add (b , line , slen )) != CRYPT_OK ) {
329+ goto error_out ;
241330 }
242- wpem += slen ;
243- slen = sizeof (buf );
331+ slen = sizeof (line );
244332 }
245- if (!hdr_ok )
246- return CRYPT_INVALID_PACKET ;
247-
248- if (would_overflow || !s_fits_buf (wpem , 1 , end )) {
249- /* NUL termination */
250- wpem ++ ;
251- /* prevent a wrap-around */
252- if (wpem < (char * )asn1_cert )
253- return CRYPT_OVERFLOW ;
254- * asn1_len = wpem - (char * )asn1_cert ;
255- return CRYPT_BUFFER_OVERFLOW ;
333+ if (!hdr_ok ) {
334+ err = CRYPT_INVALID_PACKET ;
335+ } else {
336+ slen = s_bufp_alloc_len (b );
337+ err = base64_strict_decode (b -> start , s_bufp_used_len (b ), (void * )b -> start , & slen );
256338 }
257-
258- * asn1_len = wpem - ( char * ) asn1_cert ;
259- * wpem ++ = '\0' ;
260-
261- if (( err = base64_strict_decode ( asn1_cert , * asn1_len , asn1_cert , asn1_len )) != CRYPT_OK ) {
262- return err ;
339+ if ( err == CRYPT_OK ) {
340+ * dest = b -> start ;
341+ * len = slen ;
342+ } else {
343+ error_out :
344+ XFREE ( b -> start ) ;
263345 }
264- return CRYPT_OK ;
346+ return err ;
265347}
266348
267349#endif /* LTC_PEM */
0 commit comments