[Title] Add packaging/nettle.spec to build nettle on OBS system
[external/nettle.git] / base64-encode.c
1 /* base64-encode.c
2  *
3  */
4
5 /* nettle, low-level cryptographics library
6  *
7  * Copyright (C) 2002 Niels Möller
8  *  
9  * The nettle library is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or (at your
12  * option) any later version.
13  * 
14  * The nettle library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
17  * License for more details.
18  * 
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with the nettle library; see the file COPYING.LIB.  If not, write to
21  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
22  * MA 02111-1307, USA.
23  */
24
25 #if HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <assert.h>
30 #include <stdlib.h>
31
32 #include "base64.h"
33
34 static const uint8_t encode_table[64] =
35   "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
36   "abcdefghijklmnopqrstuvwxyz"
37   "0123456789+/";
38
39 #define ENCODE(x) (encode_table[0x3F & (x)])
40
41 void
42 base64_encode_raw(uint8_t *dst, unsigned length, const uint8_t *src)
43 {
44   const uint8_t *in = src + length;
45   uint8_t *out = dst + BASE64_ENCODE_RAW_LENGTH(length);
46
47   unsigned left_over = length % 3;
48
49   if (left_over)
50     {
51       in -= left_over;
52       *--out = '=';
53       switch(left_over)
54         {
55         case 1:
56           *--out = '=';
57           *--out = ENCODE(in[0] << 4);
58           break;
59           
60         case 2:
61           *--out = ENCODE( in[1] << 2);
62           *--out = ENCODE((in[0] << 4) | (in[1] >> 4));
63           break;
64
65         default:
66           abort();
67         }
68       *--out = ENCODE(in[0] >> 2);
69     }
70   
71   while (in > src)
72     {
73       in -= 3;
74       *--out = ENCODE( in[2]);
75       *--out = ENCODE((in[1] << 2) | (in[2] >> 6));
76       *--out = ENCODE((in[0] << 4) | (in[1] >> 4));
77       *--out = ENCODE( in[0] >> 2);      
78     }
79   assert(in == src);
80   assert(out == dst);
81 }
82
83 #if 0
84 unsigned 
85 base64_encode(uint8_t *dst,
86               unsigned src_length,
87               const uint8_t *src)
88 {
89   unsigned dst_length = BASE64_ENCODE_RAW_LENGTH(src_length);
90   unsigned n = src_length / 3;
91   unsigned left_over  = src_length % 3;
92   unsigned done = 0;
93   
94   if (left_over)
95     {
96       const uint8_t *in = src + n * 3;
97       uint8_t *out = dst + dst_length;
98
99       switch(left_over)
100         {
101         case 1:
102           *--out = '=';
103           *--out = ENCODE(in[0] << 4);
104           break;
105           
106         case 2:
107           *--out = ENCODE( in[1] << 2);
108           *--out = ENCODE((in[0] << 4) | (in[1] >> 4));
109           break;
110
111         default:
112           abort();
113         }
114       *--out = ENCODE(in[0] >> 2);
115
116       done = 4;
117     }
118   base64_encode_raw(n, dst, src);
119   done += n * 4;
120
121   assert(done == dst_length);
122
123   return done;
124 }
125 #endif
126
127 void
128 base64_encode_group(uint8_t *dst, uint32_t group)
129 {
130   *dst++ = ENCODE(group >> 18);
131   *dst++ = ENCODE(group >> 12);
132   *dst++ = ENCODE(group >> 6);
133   *dst++ = ENCODE(group);
134 }
135
136 void
137 base64_encode_init(struct base64_encode_ctx *ctx)
138 {
139   ctx->word = ctx->bits = 0;
140 }
141
142 /* Encodes a single byte. */
143 unsigned
144 base64_encode_single(struct base64_encode_ctx *ctx,
145                      uint8_t *dst,
146                      uint8_t src)
147 {
148   unsigned done = 0;
149   unsigned word = ctx->word << 8 | src;
150   unsigned bits = ctx->bits + 8;
151   
152   while (bits >= 6)
153     {
154       bits -= 6;
155       dst[done++] = ENCODE(word >> bits);
156     }
157
158   ctx->bits = bits;
159   ctx->word = word;
160
161   assert(done <= 2);
162   
163   return done;
164 }
165
166 /* Returns the number of output characters. DST should point to an
167  * area of size at least BASE64_ENCODE_LENGTH(length). */
168 unsigned
169 base64_encode_update(struct base64_encode_ctx *ctx,
170                      uint8_t *dst,
171                      unsigned length,
172                      const uint8_t *src)
173 {
174   unsigned done = 0;
175   unsigned left = length;
176   unsigned left_over;
177   unsigned bulk;
178   
179   while (ctx->bits && left)
180     {
181       left--;
182       done += base64_encode_single(ctx, dst + done, *src++);
183     }
184   
185   left_over = left % 3;
186   bulk = left - left_over;
187   
188   if (bulk)
189     {
190       assert(!(bulk % 3));
191       
192       base64_encode_raw(dst + done, bulk, src);
193       done += BASE64_ENCODE_RAW_LENGTH(bulk);
194       src += bulk;
195       left = left_over;
196     }
197
198   while (left)
199     {
200       left--;
201       done += base64_encode_single(ctx, dst + done, *src++);
202     }
203
204   assert(done <= BASE64_ENCODE_LENGTH(length));
205
206   return done;
207 }
208
209 /* DST should point to an area of size at least
210  * BASE64_ENCODE_FINAL_SIZE */
211 unsigned
212 base64_encode_final(struct base64_encode_ctx *ctx,
213                     uint8_t *dst)
214 {
215   unsigned done = 0;
216   unsigned bits = ctx->bits;
217   
218   if (bits)
219     {
220       dst[done++] = ENCODE(ctx->word << (6 - ctx->bits));
221       for (; bits < 6; bits += 2)
222         dst[done++] = '=';
223
224       ctx->bits = 0;
225     }
226
227   assert(done <= BASE64_ENCODE_FINAL_LENGTH);
228   return done;
229 }