]>
git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_cryptkit/lib/enc64.c
1 /* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved.
3 * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT
4 * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE
5 * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE
6 * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE,
7 * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL
8 * EXPOSE YOU TO LIABILITY.
9 ***************************************************************************
11 * enc64.c - encode/decode in 64-char IA5 format, per RFC 1421
16 * Added ECDSA_VERIFY_ONLY dependencies.
18 * Changed to compile with C++.
20 * Newlines optional in dec64() and isValidEnc64().
29 * 11/27/98 dmitch: The ECDSA_VERIFY_ONLY symbol, when #defined, disables all
30 * of the code in this module except that which is necessary for ECDSA
31 * siggnature verification.
35 #define NULL ((void *)0)
39 * map a 6-bit binary value to a printable character.
42 unsigned char bintoasc
[] =
43 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
46 * Map an 7-bit printable character to its corresponding binary value.
47 * Any illegal characters return high bit set.
50 unsigned char asctobin
[] =
52 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
53 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
54 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
55 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
56 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
57 0x80, 0x80, 0x80, 0x3e, 0x80, 0x80, 0x80, 0x3f,
58 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
59 0x3c, 0x3d, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
60 0x80, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
61 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
62 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
63 0x17, 0x18, 0x19, 0x80, 0x80, 0x80, 0x80, 0x80,
64 0x80, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
65 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
66 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
67 0x31, 0x32, 0x33, 0x80, 0x80, 0x80, 0x80, 0x80
71 * map 6 bits to a printing char
73 #define ENC(c) (bintoasc[((c) & 0x3f)])
76 //#define ENC_LINE_LEN 64
78 #ifndef ECDSA_VERIFY_ONLY
81 * map one group of up to 3 bytes at inp to 4 bytes at outp.
82 * Count is number of valid bytes in *inp; if less than 3, the
83 * 1 or two extras must be zeros.
85 static void encChunk(const unsigned char *inp
,
89 unsigned char c1
, c2
, c3
, c4
;
92 c2
= ((inp
[0] << 4) & 0x30) | ((inp
[1] >> 4) & 0xf);
93 c3
= ((inp
[1] << 2) & 0x3c) | ((inp
[2] >> 6) & 0x3);
112 * Given input buffer inbuf, length inlen, encode to 64-char IA5 format.
113 * Result is fmalloc'd and returned; it is terminated by Microsoft-style
114 * newline and NULL. Its length (including the trailing newline and NULL)
115 * is returned in *outlen.
118 unsigned char *enc64(const unsigned char *inbuf
,
120 unsigned *outlen
) // RETURNED
122 return enc64WithLines(inbuf
, inlen
, 0, outlen
);
125 unsigned char *enc64WithLines(const unsigned char *inbuf
,
131 unsigned len
; // to malloc, liberal
132 unsigned olen
= 0; // actual output size
133 unsigned char *outbuf
;
134 unsigned char endbuf
[3];
140 outTextLen
= ((inlen
+ 2) / 3) * 4;
143 * linelen must be 0 mod 4 for this to work; round up...
145 if((linelen
& 0x03) != 0) {
146 linelen
= (linelen
+ 3) & 0xfffffffc;
148 numLines
= (outTextLen
+ linelen
- 1)/ linelen
;
155 * Total output size = encoded text size plus one newline per
156 * line of output, plus trailing NULL. For Microsoft compatibility,
157 * we always generate newlines as \r\n; when decoding, we tolerate
160 len
= outTextLen
+ (2 * numLines
) + 1;
161 outbuf
= (unsigned char*) fmalloc(len
);
169 endbuf
[i
] = inbuf
[i
];
175 encChunk(endbuf
, outp
, inlen
);
179 encChunk(inbuf
, outp
, 3);
186 if((linelen
!= 0) && (thisLine
>= linelen
) && inlen
) {
188 * last trailing newline added below
189 * Note we don't split 4-byte output chunks over newlines
205 #endif /* ECDSA_VERIFY_ONLY */
207 static inline int isWhite(unsigned char c
)
229 * Strip off all whitespace from a (supposedly) enc64-format string.
230 * Returns a malloc'd string.
232 static unsigned char *stringCleanse(const unsigned char *inbuf
,
236 unsigned char *news
; // cleansed inbuf
237 unsigned newsDex
; // index into news
240 news
= (unsigned char*) fmalloc(inlen
);
242 for(i
=0; i
<inlen
; i
++) {
243 if(!isWhite(inbuf
[i
])) {
244 news
[newsDex
++] = inbuf
[i
];
252 * Given input buffer inbuf, length inlen, decode from 64-char IA5 format to
253 * binary. Result is fmalloced and returned; its length is returned in *outlen.
254 * NULL return indicates corrupted input.
256 * All whitespace in input is ignored.
258 unsigned char *dec64(const unsigned char *inbuf
,
262 unsigned char *outbuf
;
263 unsigned char *outp
; // malloc'd outbuf size
265 const unsigned char *bp
;
266 unsigned olen
= 0; // actual output size
267 unsigned char c1
, c2
, c3
, c4
;
270 unsigned char *news
; // cleansed inbuf
274 * Strip out all whitespace; remainder must be multiple of four
277 news
= stringCleanse(inbuf
, inlen
, &newsLen
);
278 if((newsLen
& 0x03) != 0) {
280 return (unsigned char*) NULL
;
285 obuflen
= (inlen
/ 4) * 3;
286 outbuf
= (unsigned char*) fmalloc(obuflen
);
291 * Note inlen is always a multiple of four here
293 if (*bp
& 0x80 || (c1
= asctobin
[*bp
]) & 0x80) {
298 if (*bp
& 0x80 || (c2
= asctobin
[*bp
]) & 0x80){
305 * two input bytes, one output byte
324 } else if (*bp
& 0x80 || (c3
= asctobin
[*bp
]) & 0x80) {
331 * Three input bytes, two output
338 } else if (*bp
& 0x80 || (c4
= asctobin
[*bp
]) & 0x80) {
342 * Normal non-pad case
349 j
= (c1
<< 2) | (c2
>> 4);
352 j
= (c2
<< 4) | (c3
>> 2);
363 return outbuf
; /* normal return */
368 return (unsigned char*) NULL
;
372 * Determine if specified input data is valid enc64 format. Returns 1
373 * if valid, 0 if not.
374 * This doesn't do a full enc64 parse job; it scans for legal characters
375 * and proper sync when a possible pad is found.
377 int isValidEnc64(const unsigned char *inbuf
,
380 int padChars
= 0; // running count of PAD chars
381 int validEncChars
= 0;
387 * -- count valid chars
388 * -- ensure not more than 2 PAD chars, only at end
389 * -- ensure valid chars mod 4 == 0
400 return 0; // max of 2 PAD chars at end
403 else if(padChars
> 0) {
404 return 0; // no normal chars after seeing PAD
406 else if((c
& 0x80) || ((asctobin
[c
]) & 0x80)) {
407 return 0; // invalid encoded char
411 if((validEncChars
& 0x03) != 0) {