@@ -21,19 +21,35 @@ static const char * const codes_base64url =
2121"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_" ;
2222#endif /* LTC_BASE64_URL */
2323
24- static int s_base64_encode_internal (const unsigned char * in , unsigned long inlen ,
25- char * out , unsigned long * outlen ,
26- const char * codes , int pad )
24+ enum mode {
25+ nopad = 0 ,
26+ pad = 1 ,
27+ lf = 2 ,
28+ cr = 4 ,
29+ ssh = 8 ,
30+ crlf = lf | cr ,
31+ };
32+
33+ static int s_base64_encode_internal (const unsigned char * in , unsigned long inlen ,
34+ char * out , unsigned long * outlen ,
35+ const char * codes , unsigned int mode )
2736{
28- unsigned long i , len2 , leven ;
37+ unsigned long i , len2 , leven , linelen ;
2938 char * p ;
3039
3140 LTC_ARGCHK (in != NULL );
3241 LTC_ARGCHK (out != NULL );
3342 LTC_ARGCHK (outlen != NULL );
3443
44+ linelen = (mode & ssh ) ? 72 : 64 ;
45+
3546 /* valid output size ? */
3647 len2 = 4 * ((inlen + 2 ) / 3 );
48+ if ((mode & crlf ) == lf ) {
49+ len2 += len2 / linelen ;
50+ } else if ((mode & crlf ) == crlf ) {
51+ len2 += (len2 / linelen ) * 2 ;
52+ }
3753 if (* outlen < len2 + 1 ) {
3854 * outlen = len2 + 1 ;
3955 return CRYPT_BUFFER_OVERFLOW ;
@@ -46,6 +62,10 @@ static int s_base64_encode_internal(const unsigned char *in, unsigned long inle
4662 * p ++ = codes [(((in [1 ] & 0xf ) << 2 ) + (in [2 ] >> 6 )) & 0x3F ];
4763 * p ++ = codes [in [2 ] & 0x3F ];
4864 in += 3 ;
65+ if ((p - out ) % linelen == 0 ) {
66+ if (mode & cr ) * p ++ = '\r' ;
67+ if (mode & lf ) * p ++ = '\n' ;
68+ }
4969 }
5070 /* Pad it if necessary... */
5171 if (i < inlen ) {
@@ -54,7 +74,7 @@ static int s_base64_encode_internal(const unsigned char *in, unsigned long inle
5474
5575 * p ++ = codes [(a >> 2 ) & 0x3F ];
5676 * p ++ = codes [(((a & 3 ) << 4 ) + (b >> 4 )) & 0x3F ];
57- if (pad ) {
77+ if (mode & pad ) {
5878 * p ++ = (i + 1 < inlen ) ? codes [(((b & 0xf ) << 2 )) & 0x3F ] : '=' ;
5979 * p ++ = '=' ;
6080 }
@@ -83,7 +103,26 @@ static int s_base64_encode_internal(const unsigned char *in, unsigned long inle
83103int base64_encode (const unsigned char * in , unsigned long inlen ,
84104 char * out , unsigned long * outlen )
85105{
86- return s_base64_encode_internal (in , inlen , out , outlen , codes_base64 , 1 );
106+ return s_base64_encode_internal (in , inlen , out , outlen , codes_base64 , pad );
107+ }
108+
109+ /**
110+ base64 Encode a buffer for PEM output
111+ (NUL terminated with line-break at 64 chars)
112+ @param in The input buffer to encode
113+ @param inlen The length of the input buffer
114+ @param out [out] The destination of the base64 encoded data
115+ @param outlen [in/out] The max size and resulting size
116+ @param flags \ref base64_pem_flags
117+ @return CRYPT_OK if successful
118+ */
119+ int base64_encode_pem (const unsigned char * in , unsigned long inlen ,
120+ char * out , unsigned long * outlen ,
121+ unsigned int flags )
122+ {
123+ int use_crlf = flags & BASE64_PEM_CRLF ? pad | crlf : pad | lf ;
124+ int ssh_style = flags & BASE64_PEM_SSH ? ssh : 0 ;
125+ return s_base64_encode_internal (in , inlen , out , outlen , codes_base64 , ssh_style | use_crlf );
87126}
88127#endif /* LTC_BASE64 */
89128
@@ -100,13 +139,13 @@ int base64_encode(const unsigned char *in, unsigned long inlen,
100139int base64url_encode (const unsigned char * in , unsigned long inlen ,
101140 char * out , unsigned long * outlen )
102141{
103- return s_base64_encode_internal (in , inlen , out , outlen , codes_base64url , 0 );
142+ return s_base64_encode_internal (in , inlen , out , outlen , codes_base64url , nopad );
104143}
105144
106145int base64url_strict_encode (const unsigned char * in , unsigned long inlen ,
107146 char * out , unsigned long * outlen )
108147{
109- return s_base64_encode_internal (in , inlen , out , outlen , codes_base64url , 1 );
148+ return s_base64_encode_internal (in , inlen , out , outlen , codes_base64url , pad );
110149}
111150#endif /* LTC_BASE64_URL */
112151
0 commit comments