@@ -17,14 +17,98 @@ extern const struct str pem_dek_info_start;
17
17
extern const struct blockcipher_info pem_dek_infos [];
18
18
extern const unsigned long pem_dek_infos_num ;
19
19
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
+
20
78
#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 )
22
85
{
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 );
24
89
}
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
+ };
25
109
#endif /* LTC_NO_FILE */
26
110
27
- int pem_get_char_from_buf (struct get_char * g )
111
+ static int s_pem_get_char_from_buf (struct get_char * g )
28
112
{
29
113
int ret ;
30
114
if (g -> data .buf .work == g -> data .buf .end ) {
@@ -35,6 +119,25 @@ int pem_get_char_from_buf(struct get_char *g)
35
119
return ret ;
36
120
}
37
121
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
+
38
141
static void s_unget_line (char * buf , unsigned long buflen , struct get_char * g )
39
142
{
40
143
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,
81
184
while (blen < * buflen || search_for_start ) {
82
185
wr = blen < * buflen ? blen : * buflen - 1 ;
83
186
c_ = g -> prev_get ;
84
- g -> prev_get = g -> get (g );
187
+ g -> prev_get = g -> api . get (g );
85
188
if (g -> prev_get == '\n' ) {
86
189
buf [wr ] = '\0' ;
87
190
if (c_ == '\r' ) {
@@ -103,26 +206,16 @@ static char* s_get_line_i(char *buf, unsigned long *buflen, struct get_char *g,
103
206
return NULL ;
104
207
}
105
208
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 )
107
210
{
108
211
return s_get_line_i (buf , buflen , g , 1 );
109
212
}
110
213
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 )
112
215
{
113
216
return s_get_line_i (buf , buflen , g , 0 );
114
217
}
115
218
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
-
126
219
static int s_pem_decode_headers (struct pem_headers * hdr , struct get_char * g )
127
220
{
128
221
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)
190
283
return CRYPT_OK ;
191
284
}
192
285
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 )
194
287
{
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_ ;
198
290
const char pem_start [] = "----" ;
199
291
unsigned long slen , linelen ;
200
292
int err , hdr_ok = 0 ;
201
- int would_overflow = 0 ;
202
293
unsigned char empty_lines = 0 ;
203
294
204
295
g -> prev_get = 0 ;
205
296
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 ) {
208
299
if (g -> prev_get == -1 )
209
300
return CRYPT_NOP ;
210
301
else
211
302
return CRYPT_INVALID_PACKET ;
212
303
}
213
304
if (linelen < sizeof (pem_start ) - 1 )
214
305
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 );
218
309
return CRYPT_UNKNOWN_PEM ;
219
310
}
220
311
@@ -223,9 +314,9 @@ int pem_read(void *asn1_cert, unsigned long *asn1_len, struct pem_headers *hdr,
223
314
return err ;
224
315
225
316
/* 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 )) {
229
320
hdr_ok = 1 ;
230
321
break ;
231
322
}
@@ -234,34 +325,25 @@ int pem_read(void *asn1_cert, unsigned long *asn1_len, struct pem_headers *hdr,
234
325
break ;
235
326
empty_lines ++ ;
236
327
}
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 ;
241
330
}
242
- wpem += slen ;
243
- slen = sizeof (buf );
331
+ slen = sizeof (line );
244
332
}
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 );
256
338
}
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 ) ;
263
345
}
264
- return CRYPT_OK ;
346
+ return err ;
265
347
}
266
348
267
349
#endif /* LTC_PEM */
0 commit comments