@@ -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 longs_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 longs_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