Index: libsrtp/crypto/math/datatypes.c |
=================================================================== |
--- libsrtp/crypto/math/datatypes.c (revision 0) |
+++ libsrtp/crypto/math/datatypes.c (revision 0) |
@@ -0,0 +1,718 @@ |
+/* |
+ * datatypes.c |
+ * |
+ * data types for finite fields and functions for input, output, and |
+ * manipulation |
+ * |
+ * David A. McGrew |
+ * Cisco Systems, Inc. |
+ */ |
+/* |
+ * |
+ * Copyright (c) 2001-2006 Cisco Systems, Inc. |
+ * All rights reserved. |
+ * |
+ * Redistribution and use in source and binary forms, with or without |
+ * modification, are permitted provided that the following conditions |
+ * are met: |
+ * |
+ * Redistributions of source code must retain the above copyright |
+ * notice, this list of conditions and the following disclaimer. |
+ * |
+ * Redistributions in binary form must reproduce the above |
+ * copyright notice, this list of conditions and the following |
+ * disclaimer in the documentation and/or other materials provided |
+ * with the distribution. |
+ * |
+ * Neither the name of the Cisco Systems, Inc. nor the names of its |
+ * contributors may be used to endorse or promote products derived |
+ * from this software without specific prior written permission. |
+ * |
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, |
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
+ * OF THE POSSIBILITY OF SUCH DAMAGE. |
+ * |
+ */ |
+ |
+#include "datatypes.h" |
+ |
+int |
+octet_weight[256] = { |
+ 0, 1, 1, 2, 1, 2, 2, 3, |
+ 1, 2, 2, 3, 2, 3, 3, 4, |
+ 1, 2, 2, 3, 2, 3, 3, 4, |
+ 2, 3, 3, 4, 3, 4, 4, 5, |
+ 1, 2, 2, 3, 2, 3, 3, 4, |
+ 2, 3, 3, 4, 3, 4, 4, 5, |
+ 2, 3, 3, 4, 3, 4, 4, 5, |
+ 3, 4, 4, 5, 4, 5, 5, 6, |
+ 1, 2, 2, 3, 2, 3, 3, 4, |
+ 2, 3, 3, 4, 3, 4, 4, 5, |
+ 2, 3, 3, 4, 3, 4, 4, 5, |
+ 3, 4, 4, 5, 4, 5, 5, 6, |
+ 2, 3, 3, 4, 3, 4, 4, 5, |
+ 3, 4, 4, 5, 4, 5, 5, 6, |
+ 3, 4, 4, 5, 4, 5, 5, 6, |
+ 4, 5, 5, 6, 5, 6, 6, 7, |
+ 1, 2, 2, 3, 2, 3, 3, 4, |
+ 2, 3, 3, 4, 3, 4, 4, 5, |
+ 2, 3, 3, 4, 3, 4, 4, 5, |
+ 3, 4, 4, 5, 4, 5, 5, 6, |
+ 2, 3, 3, 4, 3, 4, 4, 5, |
+ 3, 4, 4, 5, 4, 5, 5, 6, |
+ 3, 4, 4, 5, 4, 5, 5, 6, |
+ 4, 5, 5, 6, 5, 6, 6, 7, |
+ 2, 3, 3, 4, 3, 4, 4, 5, |
+ 3, 4, 4, 5, 4, 5, 5, 6, |
+ 3, 4, 4, 5, 4, 5, 5, 6, |
+ 4, 5, 5, 6, 5, 6, 6, 7, |
+ 3, 4, 4, 5, 4, 5, 5, 6, |
+ 4, 5, 5, 6, 5, 6, 6, 7, |
+ 4, 5, 5, 6, 5, 6, 6, 7, |
+ 5, 6, 6, 7, 6, 7, 7, 8 |
+}; |
+ |
+int |
+octet_get_weight(uint8_t octet) { |
+ extern int octet_weight[256]; |
+ |
+ return octet_weight[octet]; |
+} |
+ |
+/* |
+ * bit_string is a buffer that is used to hold output strings, e.g. |
+ * for printing. |
+ */ |
+ |
+/* the value MAX_PRINT_STRING_LEN is defined in datatypes.h */ |
+ |
+char bit_string[MAX_PRINT_STRING_LEN]; |
+ |
+uint8_t |
+nibble_to_hex_char(uint8_t nibble) { |
+ char buf[16] = {'0', '1', '2', '3', '4', '5', '6', '7', |
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; |
+ return buf[nibble & 0xF]; |
+} |
+ |
+char * |
+octet_string_hex_string(const void *s, int length) { |
+ const uint8_t *str = (const uint8_t *)s; |
+ int i; |
+ |
+ /* double length, since one octet takes two hex characters */ |
+ length *= 2; |
+ |
+ /* truncate string if it would be too long */ |
+ if (length > MAX_PRINT_STRING_LEN) |
+ length = MAX_PRINT_STRING_LEN-1; |
+ |
+ for (i=0; i < length; i+=2) { |
+ bit_string[i] = nibble_to_hex_char(*str >> 4); |
+ bit_string[i+1] = nibble_to_hex_char(*str++ & 0xF); |
+ } |
+ bit_string[i] = 0; /* null terminate string */ |
+ return bit_string; |
+} |
+ |
+inline int |
+hex_char_to_nibble(uint8_t c) { |
+ switch(c) { |
+ case ('0'): return 0x0; |
+ case ('1'): return 0x1; |
+ case ('2'): return 0x2; |
+ case ('3'): return 0x3; |
+ case ('4'): return 0x4; |
+ case ('5'): return 0x5; |
+ case ('6'): return 0x6; |
+ case ('7'): return 0x7; |
+ case ('8'): return 0x8; |
+ case ('9'): return 0x9; |
+ case ('a'): return 0xa; |
+ case ('A'): return 0xa; |
+ case ('b'): return 0xb; |
+ case ('B'): return 0xb; |
+ case ('c'): return 0xc; |
+ case ('C'): return 0xc; |
+ case ('d'): return 0xd; |
+ case ('D'): return 0xd; |
+ case ('e'): return 0xe; |
+ case ('E'): return 0xe; |
+ case ('f'): return 0xf; |
+ case ('F'): return 0xf; |
+ default: return -1; /* this flags an error */ |
+ } |
+ /* NOTREACHED */ |
+ return -1; /* this keeps compilers from complaining */ |
+} |
+ |
+int |
+is_hex_string(char *s) { |
+ while(*s != 0) |
+ if (hex_char_to_nibble(*s++) == -1) |
+ return 0; |
+ return 1; |
+} |
+ |
+/* |
+ * hex_string_to_octet_string converts a hexadecimal string |
+ * of length 2 * len to a raw octet string of length len |
+ */ |
+ |
+int |
+hex_string_to_octet_string(char *raw, char *hex, int len) { |
+ uint8_t x; |
+ int tmp; |
+ int hex_len; |
+ |
+ hex_len = 0; |
+ while (hex_len < len) { |
+ tmp = hex_char_to_nibble(hex[0]); |
+ if (tmp == -1) |
+ return hex_len; |
+ x = (tmp << 4); |
+ hex_len++; |
+ tmp = hex_char_to_nibble(hex[1]); |
+ if (tmp == -1) |
+ return hex_len; |
+ x |= (tmp & 0xff); |
+ hex_len++; |
+ *raw++ = x; |
+ hex += 2; |
+ } |
+ return hex_len; |
+} |
+ |
+char * |
+v128_hex_string(v128_t *x) { |
+ int i, j; |
+ |
+ for (i=j=0; i < 16; i++) { |
+ bit_string[j++] = nibble_to_hex_char(x->v8[i] >> 4); |
+ bit_string[j++] = nibble_to_hex_char(x->v8[i] & 0xF); |
+ } |
+ |
+ bit_string[j] = 0; /* null terminate string */ |
+ return bit_string; |
+} |
+ |
+char * |
+v128_bit_string(v128_t *x) { |
+ int j, i; |
+ uint32_t mask; |
+ |
+ for (j=i=0; j < 4; j++) { |
+ for (mask=0x80000000; mask > 0; mask >>= 1) { |
+ if (x->v32[j] & mask) |
+ bit_string[i] = '1'; |
+ else |
+ bit_string[i] = '0'; |
+ ++i; |
+ } |
+ } |
+ bit_string[128] = 0; /* null terminate string */ |
+ |
+ return bit_string; |
+} |
+ |
+void |
+v128_copy_octet_string(v128_t *x, const uint8_t s[16]) { |
+#ifdef ALIGNMENT_32BIT_REQUIRED |
+ if ((((uint32_t) &s[0]) & 0x3) != 0) |
+#endif |
+ { |
+ x->v8[0] = s[0]; |
+ x->v8[1] = s[1]; |
+ x->v8[2] = s[2]; |
+ x->v8[3] = s[3]; |
+ x->v8[4] = s[4]; |
+ x->v8[5] = s[5]; |
+ x->v8[6] = s[6]; |
+ x->v8[7] = s[7]; |
+ x->v8[8] = s[8]; |
+ x->v8[9] = s[9]; |
+ x->v8[10] = s[10]; |
+ x->v8[11] = s[11]; |
+ x->v8[12] = s[12]; |
+ x->v8[13] = s[13]; |
+ x->v8[14] = s[14]; |
+ x->v8[15] = s[15]; |
+ } |
+#ifdef ALIGNMENT_32BIT_REQUIRED |
+ else |
+ { |
+ v128_t *v = (v128_t *) &s[0]; |
+ |
+ v128_copy(x,v); |
+ } |
+#endif |
+} |
+ |
+#ifndef DATATYPES_USE_MACROS /* little functions are not macros */ |
+ |
+void |
+v128_set_to_zero(v128_t *x) { |
+ _v128_set_to_zero(x); |
+} |
+ |
+void |
+v128_copy(v128_t *x, const v128_t *y) { |
+ _v128_copy(x, y); |
+} |
+ |
+void |
+v128_xor(v128_t *z, v128_t *x, v128_t *y) { |
+ _v128_xor(z, x, y); |
+} |
+ |
+void |
+v128_and(v128_t *z, v128_t *x, v128_t *y) { |
+ _v128_and(z, x, y); |
+} |
+ |
+void |
+v128_or(v128_t *z, v128_t *x, v128_t *y) { |
+ _v128_or(z, x, y); |
+} |
+ |
+void |
+v128_complement(v128_t *x) { |
+ _v128_complement(x); |
+} |
+ |
+int |
+v128_is_eq(const v128_t *x, const v128_t *y) { |
+ return _v128_is_eq(x, y); |
+} |
+ |
+int |
+v128_xor_eq(v128_t *x, const v128_t *y) { |
+ return _v128_xor_eq(x, y); |
+} |
+ |
+int |
+v128_get_bit(const v128_t *x, int i) { |
+ return _v128_get_bit(x, i); |
+} |
+ |
+void |
+v128_set_bit(v128_t *x, int i) { |
+ _v128_set_bit(x, i); |
+} |
+ |
+void |
+v128_clear_bit(v128_t *x, int i){ |
+ _v128_clear_bit(x, i); |
+} |
+ |
+void |
+v128_set_bit_to(v128_t *x, int i, int y){ |
+ _v128_set_bit_to(x, i, y); |
+} |
+ |
+ |
+#endif /* DATATYPES_USE_MACROS */ |
+ |
+void |
+v128_right_shift(v128_t *x, int shift) { |
+ const int base_index = shift >> 5; |
+ const int bit_index = shift & 31; |
+ int i, from; |
+ uint32_t b; |
+ |
+ if (shift > 127) { |
+ v128_set_to_zero(x); |
+ return; |
+ } |
+ |
+ if (bit_index == 0) { |
+ |
+ /* copy each word from left size to right side */ |
+ x->v32[4-1] = x->v32[4-1-base_index]; |
+ for (i=4-1; i > base_index; i--) |
+ x->v32[i-1] = x->v32[i-1-base_index]; |
+ |
+ } else { |
+ |
+ /* set each word to the "or" of the two bit-shifted words */ |
+ for (i = 4; i > base_index; i--) { |
+ from = i-1 - base_index; |
+ b = x->v32[from] << bit_index; |
+ if (from > 0) |
+ b |= x->v32[from-1] >> (32-bit_index); |
+ x->v32[i-1] = b; |
+ } |
+ |
+ } |
+ |
+ /* now wrap up the final portion */ |
+ for (i=0; i < base_index; i++) |
+ x->v32[i] = 0; |
+ |
+} |
+ |
+void |
+v128_left_shift(v128_t *x, int shift) { |
+ int i; |
+ const int base_index = shift >> 5; |
+ const int bit_index = shift & 31; |
+ |
+ if (shift > 127) { |
+ v128_set_to_zero(x); |
+ return; |
+ } |
+ |
+ if (bit_index == 0) { |
+ for (i=0; i < 4 - base_index; i++) |
+ x->v32[i] = x->v32[i+base_index]; |
+ } else { |
+ for (i=0; i < 4 - base_index - 1; i++) |
+ x->v32[i] = (x->v32[i+base_index] >> bit_index) ^ |
+ (x->v32[i+base_index+1] << (32 - bit_index)); |
+ x->v32[4 - base_index-1] = x->v32[4-1] >> bit_index; |
+ } |
+ |
+ /* now wrap up the final portion */ |
+ for (i = 4 - base_index; i < 4; i++) |
+ x->v32[i] = 0; |
+ |
+} |
+ |
+/* functions manipulating bitvector_t */ |
+ |
+#ifndef DATATYPES_USE_MACROS /* little functions are not macros */ |
+ |
+int |
+bitvector_get_bit(const bitvector_t *v, int bit_index) |
+{ |
+ return _bitvector_get_bit(v, bit_index); |
+} |
+ |
+void |
+bitvector_set_bit(bitvector_t *v, int bit_index) |
+{ |
+ _bitvector_set_bit(v, bit_index); |
+} |
+ |
+void |
+bitvector_clear_bit(bitvector_t *v, int bit_index) |
+{ |
+ _bitvector_clear_bit(v, bit_index); |
+} |
+ |
+ |
+#endif /* DATATYPES_USE_MACROS */ |
+ |
+int |
+bitvector_alloc(bitvector_t *v, unsigned long length) { |
+ unsigned long l; |
+ |
+ /* Round length up to a multiple of bits_per_word */ |
+ length = (length + bits_per_word - 1) & ~(unsigned long)((bits_per_word - 1)); |
+ |
+ l = length / bits_per_word * bytes_per_word; |
+ |
+ /* allocate memory, then set parameters */ |
+ if (l == 0) |
+ v->word = NULL; |
+ else { |
+ v->word = (uint32_t*)crypto_alloc(l); |
+ if (v->word == NULL) { |
+ v->word = NULL; |
+ v->length = 0; |
+ return -1; |
+ } |
+ } |
+ v->length = length; |
+ |
+ /* initialize bitvector to zero */ |
+ bitvector_set_to_zero(v); |
+ |
+ return 0; |
+} |
+ |
+ |
+void |
+bitvector_dealloc(bitvector_t *v) { |
+ if (v->word != NULL) |
+ crypto_free(v->word); |
+ v->word = NULL; |
+ v->length = 0; |
+} |
+ |
+void |
+bitvector_set_to_zero(bitvector_t *x) |
+{ |
+ /* C99 guarantees that memset(0) will set the value 0 for uint32_t */ |
+ memset(x->word, 0, x->length >> 3); |
+} |
+ |
+char * |
+bitvector_bit_string(bitvector_t *x, char* buf, int len) { |
+ int j, i; |
+ uint32_t mask; |
+ |
+ for (j=i=0; j < (int)(x->length>>5) && i < len-1; j++) { |
+ for (mask=0x80000000; mask > 0; mask >>= 1) { |
+ if (x->word[j] & mask) |
+ buf[i] = '1'; |
+ else |
+ buf[i] = '0'; |
+ ++i; |
+ if (i >= len-1) |
+ break; |
+ } |
+ } |
+ buf[i] = 0; /* null terminate string */ |
+ |
+ return buf; |
+} |
+ |
+void |
+bitvector_left_shift(bitvector_t *x, int shift) { |
+ int i; |
+ const int base_index = shift >> 5; |
+ const int bit_index = shift & 31; |
+ const int word_length = x->length >> 5; |
+ |
+ if (shift >= (int)x->length) { |
+ bitvector_set_to_zero(x); |
+ return; |
+ } |
+ |
+ if (bit_index == 0) { |
+ for (i=0; i < word_length - base_index; i++) |
+ x->word[i] = x->word[i+base_index]; |
+ } else { |
+ for (i=0; i < word_length - base_index - 1; i++) |
+ x->word[i] = (x->word[i+base_index] >> bit_index) ^ |
+ (x->word[i+base_index+1] << (32 - bit_index)); |
+ x->word[word_length - base_index-1] = x->word[word_length-1] >> bit_index; |
+ } |
+ |
+ /* now wrap up the final portion */ |
+ for (i = word_length - base_index; i < word_length; i++) |
+ x->word[i] = 0; |
+ |
+} |
+ |
+ |
+int |
+octet_string_is_eq(uint8_t *a, uint8_t *b, int len) { |
+ uint8_t *end = b + len; |
+ while (b < end) |
+ if (*a++ != *b++) |
+ return 1; |
+ return 0; |
+} |
+ |
+void |
+octet_string_set_to_zero(uint8_t *s, int len) { |
+ uint8_t *end = s + len; |
+ |
+ do { |
+ *s = 0; |
+ } while (++s < end); |
+ |
+} |
+ |
+ |
+/* |
+ * From RFC 1521: The Base64 Alphabet |
+ * |
+ * Value Encoding Value Encoding Value Encoding Value Encoding |
+ * 0 A 17 R 34 i 51 z |
+ * 1 B 18 S 35 j 52 0 |
+ * 2 C 19 T 36 k 53 1 |
+ * 3 D 20 U 37 l 54 2 |
+ * 4 E 21 V 38 m 55 3 |
+ * 5 F 22 W 39 n 56 4 |
+ * 6 G 23 X 40 o 57 5 |
+ * 7 H 24 Y 41 p 58 6 |
+ * 8 I 25 Z 42 q 59 7 |
+ * 9 J 26 a 43 r 60 8 |
+ * 10 K 27 b 44 s 61 9 |
+ * 11 L 28 c 45 t 62 + |
+ * 12 M 29 d 46 u 63 / |
+ * 13 N 30 e 47 v |
+ * 14 O 31 f 48 w (pad) = |
+ * 15 P 32 g 49 x |
+ * 16 Q 33 h 50 y |
+ */ |
+ |
+int |
+base64_char_to_sextet(uint8_t c) { |
+ switch(c) { |
+ case 'A': |
+ return 0; |
+ case 'B': |
+ return 1; |
+ case 'C': |
+ return 2; |
+ case 'D': |
+ return 3; |
+ case 'E': |
+ return 4; |
+ case 'F': |
+ return 5; |
+ case 'G': |
+ return 6; |
+ case 'H': |
+ return 7; |
+ case 'I': |
+ return 8; |
+ case 'J': |
+ return 9; |
+ case 'K': |
+ return 10; |
+ case 'L': |
+ return 11; |
+ case 'M': |
+ return 12; |
+ case 'N': |
+ return 13; |
+ case 'O': |
+ return 14; |
+ case 'P': |
+ return 15; |
+ case 'Q': |
+ return 16; |
+ case 'R': |
+ return 17; |
+ case 'S': |
+ return 18; |
+ case 'T': |
+ return 19; |
+ case 'U': |
+ return 20; |
+ case 'V': |
+ return 21; |
+ case 'W': |
+ return 22; |
+ case 'X': |
+ return 23; |
+ case 'Y': |
+ return 24; |
+ case 'Z': |
+ return 25; |
+ case 'a': |
+ return 26; |
+ case 'b': |
+ return 27; |
+ case 'c': |
+ return 28; |
+ case 'd': |
+ return 29; |
+ case 'e': |
+ return 30; |
+ case 'f': |
+ return 31; |
+ case 'g': |
+ return 32; |
+ case 'h': |
+ return 33; |
+ case 'i': |
+ return 34; |
+ case 'j': |
+ return 35; |
+ case 'k': |
+ return 36; |
+ case 'l': |
+ return 37; |
+ case 'm': |
+ return 38; |
+ case 'n': |
+ return 39; |
+ case 'o': |
+ return 40; |
+ case 'p': |
+ return 41; |
+ case 'q': |
+ return 42; |
+ case 'r': |
+ return 43; |
+ case 's': |
+ return 44; |
+ case 't': |
+ return 45; |
+ case 'u': |
+ return 46; |
+ case 'v': |
+ return 47; |
+ case 'w': |
+ return 48; |
+ case 'x': |
+ return 49; |
+ case 'y': |
+ return 50; |
+ case 'z': |
+ return 51; |
+ case '0': |
+ return 52; |
+ case '1': |
+ return 53; |
+ case '2': |
+ return 54; |
+ case '3': |
+ return 55; |
+ case '4': |
+ return 56; |
+ case '5': |
+ return 57; |
+ case '6': |
+ return 58; |
+ case '7': |
+ return 59; |
+ case '8': |
+ return 60; |
+ case '9': |
+ return 61; |
+ case '+': |
+ return 62; |
+ case '/': |
+ return 63; |
+ case '=': |
+ return 64; |
+ default: |
+ break; |
+ } |
+ return -1; |
+} |
+ |
+/* |
+ * base64_string_to_octet_string converts a hexadecimal string |
+ * of length 2 * len to a raw octet string of length len |
+ */ |
+ |
+int |
+base64_string_to_octet_string(char *raw, char *base64, int len) { |
+ uint8_t x; |
+ int tmp; |
+ int base64_len; |
+ |
+ base64_len = 0; |
+ while (base64_len < len) { |
+ tmp = base64_char_to_sextet(base64[0]); |
+ if (tmp == -1) |
+ return base64_len; |
+ x = (tmp << 6); |
+ base64_len++; |
+ tmp = base64_char_to_sextet(base64[1]); |
+ if (tmp == -1) |
+ return base64_len; |
+ x |= (tmp & 0xffff); |
+ base64_len++; |
+ *raw++ = x; |
+ base64 += 2; |
+ } |
+ return base64_len; |
+} |
Property changes on: libsrtp/crypto/math/datatypes.c |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |