@@ -17,14 +17,76 @@ 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 )
2280{
23- return getc (g -> data .f );
81+ return getc (g -> data .f . f );
2482}
83+
84+ const struct get_char_api get_char_filehandle_api = {
85+ .get = s_pem_get_char_from_file ,
86+ };
2587#endif /* LTC_NO_FILE */
2688
27- int pem_get_char_from_buf (struct get_char * g )
89+ static int s_pem_get_char_from_buf (struct get_char * g )
2890{
2991 int ret ;
3092 if (g -> data .buf .work == g -> data .buf .end ) {
@@ -35,6 +97,10 @@ int pem_get_char_from_buf(struct get_char *g)
3597 return ret ;
3698}
3799
100+ const struct get_char_api get_char_buffer_api = {
101+ .get = s_pem_get_char_from_buf ,
102+ };
103+
38104static void s_unget_line (char * buf , unsigned long buflen , struct get_char * g )
39105{
40106 if (buflen > sizeof (g -> unget_buf_ ))
@@ -81,14 +147,15 @@ static char* s_get_line_i(char *buf, unsigned long *buflen, struct get_char *g,
81147 while (blen < * buflen || search_for_start ) {
82148 wr = blen < * buflen ? blen : * buflen - 1 ;
83149 c_ = g -> prev_get ;
84- g -> prev_get = g -> get (g );
150+ g -> prev_get = g -> api . get (g );
85151 if (g -> prev_get == '\n' ) {
86152 buf [wr ] = '\0' ;
87153 if (c_ == '\r' ) {
88154 buf [-- wr ] = '\0' ;
89155 }
90156 s_tts (buf , & wr );
91157 * buflen = wr ;
158+ g -> total_read ++ ;
92159 return buf ;
93160 }
94161 if (g -> prev_get == -1 || g -> prev_get == '\0' ) {
@@ -99,30 +166,21 @@ static char* s_get_line_i(char *buf, unsigned long *buflen, struct get_char *g,
99166 }
100167 buf [wr ] = g -> prev_get ;
101168 blen ++ ;
169+ g -> total_read ++ ;
102170 }
103171 return NULL ;
104172}
105173
106- LTC_INLINE static char * s_get_first_line (char * buf , unsigned long * buflen , struct get_char * g )
174+ static LTC_INLINE char * s_get_first_line (char * buf , unsigned long * buflen , struct get_char * g )
107175{
108176 return s_get_line_i (buf , buflen , g , 1 );
109177}
110178
111- LTC_INLINE static char * s_get_line (char * buf , unsigned long * buflen , struct get_char * g )
179+ static LTC_INLINE char * s_get_line (char * buf , unsigned long * buflen , struct get_char * g )
112180{
113181 return s_get_line_i (buf , buflen , g , 0 );
114182}
115183
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-
126184static int s_pem_decode_headers (struct pem_headers * hdr , struct get_char * g )
127185{
128186 char buf [LTC_PEM_DECODE_BUFSZ ], * alg_start ;
@@ -190,31 +248,30 @@ static int s_pem_decode_headers(struct pem_headers *hdr, struct get_char *g)
190248 return CRYPT_OK ;
191249}
192250
193- int pem_read (void * asn1_cert , unsigned long * asn1_len , struct pem_headers * hdr , struct get_char * g )
251+ int pem_read (void * * dest , unsigned long * len , struct pem_headers * hdr , struct get_char * g )
194252{
195- char buf [LTC_PEM_DECODE_BUFSZ ];
196- char * wpem = asn1_cert ;
197- char * end = wpem + * asn1_len ;
253+ char line [LTC_PEM_DECODE_BUFSZ ];
254+ struct bufp b_ = {0 }, * b = & b_ ;
198255 const char pem_start [] = "----" ;
199- unsigned long slen , linelen ;
256+ unsigned long slen , read_len = 0 ;
200257 int err , hdr_ok = 0 ;
201- int would_overflow = 0 ;
202258 unsigned char empty_lines = 0 ;
203259
204260 g -> prev_get = 0 ;
205261 do {
206- linelen = sizeof (buf );
207- if (s_get_first_line (buf , & linelen , g ) == NULL ) {
262+ slen = sizeof (line );
263+ if (s_get_first_line (line , & slen , g ) == NULL ) {
208264 if (g -> prev_get == -1 )
209265 return CRYPT_NOP ;
210266 else
211267 return CRYPT_INVALID_PACKET ;
212268 }
213- if (linelen < sizeof (pem_start ) - 1 )
269+ read_len += slen ;
270+ if (slen < sizeof (pem_start ) - 1 )
214271 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 );
272+ } while (XMEMCMP (line , pem_start , sizeof (pem_start ) - 1 ) != 0 );
273+ if (hdr -> id -> start .len != slen || XMEMCMP (line , hdr -> id -> start .p , hdr -> id -> start .len )) {
274+ s_unget_line (line , slen , g );
218275 return CRYPT_UNKNOWN_PEM ;
219276 }
220277
@@ -223,9 +280,10 @@ int pem_read(void *asn1_cert, unsigned long *asn1_len, struct pem_headers *hdr,
223280 return err ;
224281
225282 /* 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 )) {
283+ slen = sizeof (line );
284+ while (s_get_line (line , & slen , g )) {
285+ read_len += slen ;
286+ if (slen == hdr -> id -> end .len && !XMEMCMP (line , hdr -> id -> end .p , slen )) {
229287 hdr_ok = 1 ;
230288 break ;
231289 }
@@ -234,34 +292,26 @@ int pem_read(void *asn1_cert, unsigned long *asn1_len, struct pem_headers *hdr,
234292 break ;
235293 empty_lines ++ ;
236294 }
237- if (!would_overflow && s_fits_buf (wpem , slen , end )) {
238- XMEMCPY (wpem , buf , slen );
239- } else {
240- would_overflow = 1 ;
295+ if ((err = s_bufp_add (b , line , slen )) != CRYPT_OK ) {
296+ goto error_out ;
241297 }
242- wpem += slen ;
243- slen = sizeof (buf );
298+ slen = sizeof (line );
244299 }
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 ;
300+ if (!hdr_ok ) {
301+ err = CRYPT_INVALID_PACKET ;
302+ } else {
303+ slen = s_bufp_alloc_len (b );
304+ err = base64_strict_decode (b -> start , s_bufp_used_len (b ), (void * )b -> start , & slen );
256305 }
306+ if (err == CRYPT_OK ) {
307+ * dest = b -> start ;
308+ * len = slen ;
257309
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 ;
310+ } else {
311+ error_out :
312+ XFREE (b -> start );
263313 }
264- return CRYPT_OK ;
314+ return err ;
265315}
266316
267317#endif /* LTC_PEM */
0 commit comments