* ccn.h
* corecrypto
*
- * Created by Michael Brouwer on 7/25/10.
- * Copyright 2010,2011 Apple Inc. All rights reserved.
+ * Created on 11/16/2010
+ *
+ * Copyright (c) 2010,2011,2012,2013,2014,2015 Apple Inc. All rights reserved.
*
*/
#ifndef _CORECRYPTO_CCN_H_
#define _CORECRYPTO_CCN_H_
-#include <corecrypto/cc_config.h>
-#include <corecrypto/cc_priv.h> /* TODO: Get rid of this include in this header. */
+#include <corecrypto/cc.h>
#include <stdint.h>
#include <stdarg.h>
-
typedef uint8_t cc_byte;
-typedef size_t cc_size;
+typedef size_t cc_size;
#if CCN_UNIT_SIZE == 8
typedef uint64_t cc_unit; // 64 bit unit
-//typedef uint128_t cc_dunit; // 128 bit double width unit
+typedef int64_t cc_int;
#define CCN_LOG2_BITS_PER_UNIT 6 // 2^6 = 64 bits
#define CC_UNIT_C(x) UINT64_C(x)
+ #if CCN_UINT128_SUPPORT_FOR_64BIT_ARCH
+ typedef unsigned cc_dunit __attribute__((mode(TI))); // 128 bit double width unit
+ typedef signed cc_dint __attribute__((mode(TI)));
+ #else
+ typedef struct cc_dunit {
+ uint64_t l; //do not change the order of the variables. cc_dunit must be little endian
+ uint64_t h;
+ } cc_dunit;
+
+ typedef struct cc_dint {
+ uint64_t l;
+ uint64_t h;
+ } cc_dint;
+ #endif
+
#elif CCN_UNIT_SIZE == 4
typedef uint32_t cc_unit; // 32 bit unit
typedef uint64_t cc_dunit; // 64 bit double width unit
+typedef int64_t cc_dint;
+typedef int32_t cc_int;
#define CCN_LOG2_BITS_PER_UNIT 5 // 2^5 = 32 bits
#define CC_UNIT_C(x) UINT32_C(x)
+
#elif CCN_UNIT_SIZE == 2
typedef uint16_t cc_unit; // 16 bit unit
typedef uint32_t cc_dunit; // 32 bit double width unit
#define CCN_LOG2_BITS_PER_UNIT 4 // 2^4 = 16 bits
#define CC_UNIT_C(x) UINT16_C(x)
+
#elif CCN_UNIT_SIZE == 1
typedef uint8_t cc_unit; // 8 bit unit
typedef uint16_t cc_dunit; // 16 bit double width unit
#define CCN_LOG2_BITS_PER_UNIT 3 // 2^3 = 8 bits
#define CC_UNIT_C(x) UINT8_C(x)
+
#else
#error invalid CCN_UNIT_SIZE
#endif
#define CCN_UNIT_BITS (sizeof(cc_unit) * 8)
#define CCN_UNIT_MASK ((cc_unit)~0)
+typedef struct {
+ cc_unit *start; // First cc_unit of the workspace
+ cc_unit *end; // address and beyond NOT TO BE TOUCHED
+} cc_ws,*cc_ws_t;
/* Conversions between n sizeof and bits */
#define ccn_sizeof_n(_n_) (sizeof(cc_unit) * (_n_))
/* Returns the count (n) of a ccn vector that can represent _bits_. */
-#define ccn_nof(_bits_) (((_bits_) + CCN_UNIT_BITS - 1) / CCN_UNIT_BITS)
+#define ccn_nof(_bits_) (((_bits_) + CCN_UNIT_BITS - 1) >> CCN_LOG2_BITS_PER_UNIT)
/* Returns the sizeof a ccn vector that can represent _bits_. */
#define ccn_sizeof(_bits_) (ccn_sizeof_n(ccn_nof(_bits_)))
/* Returns the count (n) of a ccn vector that can represent _size_ bytes. */
#define ccn_nof_size(_size_) (((_size_) + CCN_UNIT_SIZE - 1) / CCN_UNIT_SIZE)
+#define ccn_nof_sizeof(_expr_) ccn_nof_size(sizeof (_expr_))
+
/* Return the max number of bits a ccn vector of _n_ units can hold. */
#define ccn_bitsof_n(_n_) ((_n_) * CCN_UNIT_BITS)
/* Returns the value of bit _k_ of _ccn_, both are only evaluated once. */
#define ccn_bit(_ccn_, _k_) ({__typeof__ (_k_) __k = (_k_); \
- 1 & ((_ccn_)[__k / CCN_UNIT_BITS] >> (__k & (CCN_UNIT_BITS - 1)));})
+ 1 & ((_ccn_)[ __k >> CCN_LOG2_BITS_PER_UNIT] >> (__k & (CCN_UNIT_BITS - 1)));})
+/* Set the value of bit _k_ of _ccn_ to the value _v_ */
#define ccn_set_bit(_ccn_, _k_, _v_) ({__typeof__ (_k_) __k = (_k_); \
if (_v_) \
- (_ccn_)[__k/CCN_UNIT_BITS] |= CC_UNIT_C(1) << (__k & (CCN_UNIT_BITS - 1)); \
+ (_ccn_)[ __k >> CCN_LOG2_BITS_PER_UNIT] |= CC_UNIT_C(1) << (__k & (CCN_UNIT_BITS - 1)); \
else \
- (_ccn_)[__k/CCN_UNIT_BITS] &= ~(CC_UNIT_C(1) << (__k & (CCN_UNIT_BITS - 1))); \
+ (_ccn_)[ __k >> CCN_LOG2_BITS_PER_UNIT] &= ~(CC_UNIT_C(1) << (__k & (CCN_UNIT_BITS - 1))); \
})
/* Macros for making ccn constants. You must use list of CCN64_C() instances
64 bit units respectively. */
#if CCN_UNIT_SIZE == 8
-#define ccn64_32(a1,a0) (((cc_unit)a1) << 32 | ((cc_unit)a0))
+#define ccn64_32(a1,a0) (((const cc_unit)a1) << 32 | ((const cc_unit)a0))
#define ccn32_32(a0) a0
#if __LITTLE_ENDIAN__
-#define ccn32_32_parse(p,i) (((uint32_t *)p)[i])
+#define ccn32_32_parse(p,i) (((const uint32_t *)p)[i])
#else
-#define ccn32_32_parse(p,i) (((uint32_t *)p)[i^1])
+#define ccn32_32_parse(p,i) (((const uint32_t *)p)[i^1])
#endif
#define ccn32_32_null 0
#define CCN224_N ccn_nof(224)
#define CCN256_N ccn_nof(256)
#define CCN384_N ccn_nof(384)
+#define CCN512_N ccn_nof(512)
#define CCN521_N ccn_nof(521)
-#if defined(_ARM_ARCH_6) || defined(_ARM_ARCH_7)
-#if CCN_USE_BUILTIN_CLZ
-CC_INLINE CC_CONST
-cc_unit cc_clz(cc_unit data)
-{
- return __builtin_clzl(data);
-}
-#else
-CC_INLINE CC_CONST
-cc_unit cc_clz(cc_unit data)
-{
- __asm__ ("clz %0, %1\n" : "=l" (data) : "l" (data));
- return data;
-}
-#endif /* CCN_USE_BUILTIN_CLZ */
-#endif /* !defined(_ARM_ARCH_6) && !defined(_ARM_ARCH_7) */
-
-
-#if CCN_N_INLINE
-/* Return the number of used units after stripping leading 0 units. */
-CC_INLINE CC_PURE CC_NONNULL2
-cc_size ccn_n(cc_size n, const cc_unit *s) {
-#if 1
- while (n-- && s[n] == 0) {}
- return n + 1;
-#elif 0
- while (n && s[n - 1] == 0) {
- n -= 1;
- }
- return n;
-#else
- if (n & 1) {
- if (s[n - 1])
- return n;
- n &= ~1;
- }
- if (n & 2) {
- cc_unit a[2] = { s[n - 1], s[n - 2] };
- if (a[0])
- return n - 1;
- if (a[1])
- return n - 2;
- n &= ~2;
- }
- while (n) {
- cc_unit a[4] = { s[n - 1], s[n - 2], s[n - 3], s[n - 4] };
- if (a[0])
- return n - 1;
- if (a[1])
- return n - 2;
- if (a[2])
- return n - 3;
- if (a[3])
- return n - 4;
- n -= 4;
- }
- return n;
-#endif
-}
-#else
/* Return the number of used units after stripping leading 0 units. */
-CC_PURE CC_NONNULL2
+CC_PURE CC_NONNULL((2))
cc_size ccn_n(cc_size n, const cc_unit *s);
-#endif
/* s >> k -> r return bits shifted out of least significant word in bits [0, n>
{ N bit, scalar -> N bit } N = n * sizeof(cc_unit) * 8
word shifts. */
CC_NONNULL((2, 3))
cc_unit ccn_shift_right(cc_size n, cc_unit *r, const cc_unit *s, size_t k);
-CC_NONNULL((2, 3))
-void ccn_shift_right_multi(cc_size n, cc_unit *r,const cc_unit *s, size_t k);
-
-/* s << k -> r return bits shifted out of most significant word in bits [0, n>
- { N bit, scalar -> N bit } N = n * sizeof(cc_unit) * 8
- the _multi version doesn't return the shifted bits, but does support multiple
- word shifts */
-CC_NONNULL((2, 3))
-cc_unit ccn_shift_left(cc_size n, cc_unit *r, const cc_unit *s, size_t k);
-CC_NONNULL((2, 3))
-void ccn_shift_left_multi(cc_size n, cc_unit *r, const cc_unit *s, size_t k);
/* s == 0 -> return 0 | s > 0 -> return index (starting at 1) of most
significant bit that is 1.
{ N bit } N = n * sizeof(cc_unit) * 8 */
-CC_NONNULL2
+CC_NONNULL((2))
size_t ccn_bitlen(cc_size n, const cc_unit *s);
-/* Returns the number of bits which are zero before the first one bit
- counting from least to most significant bit. */
-CC_NONNULL2
-size_t ccn_trailing_zeros(cc_size n, const cc_unit *s);
-
/* s == 0 -> return true | s != 0 -> return false
{ N bit } N = n * sizeof(cc_unit) * 8 */
#define ccn_is_zero(_n_, _s_) (!ccn_n(_n_, _s_))
#define ccn_is_zero_or_one(_n_, _s_) (((_n_)==0) || ((ccn_n(_n_, _s_) <= 1) && (_s_[0] <= 1)))
-#if CCN_CMP_INLINE
-CC_INLINE CC_PURE CC_NONNULL((2, 3))
-int ccn_cmp(cc_size n, const cc_unit *s, const cc_unit *t) {
- while (n) {
- n--;
- cc_unit si = s[n];
- cc_unit ti = t[n];
- if (si != ti)
- return si > ti ? 1 : -1;
- }
- return n;
-}
-#else
/* s < t -> return - 1 | s == t -> return 0 | s > t -> return 1
{ N bit, N bit -> int } N = n * sizeof(cc_unit) * 8 */
CC_PURE CC_NONNULL((2, 3))
int ccn_cmp(cc_size n, const cc_unit *s, const cc_unit *t);
-#endif
/* s < t -> return - 1 | s == t -> return 0 | s > t -> return 1
{ N bit, M bit -> int } N = ns * sizeof(cc_unit) * 8 M = nt * sizeof(cc_unit) * 8 */
return ccn_add1(n - nt, r + nt, s + nt, ccn_add(nt, r, s, t));
}
-CC_NONNULL((4, 5))
-void ccn_divmod(cc_size n, cc_unit *q, cc_unit *r, const cc_unit *s, const cc_unit *t);
-
-
-CC_NONNULL((2, 3, 4))
-void ccn_lcm(cc_size n, cc_unit *r2n, const cc_unit *s, const cc_unit *t);
-
/* s * t -> r_2n r_2n must not overlap with s nor t
{ n bit, n bit -> 2 * n bit } n = count * sizeof(cc_unit) * 8
void ccn_mod(cc_size n, cc_unit *r, const cc_unit *a_2n, const cc_unit *d);
#endif
-/* r = gcd(s, t).
- N bit, N bit -> N bit */
-CC_NONNULL((2, 3, 4))
-void ccn_gcd(cc_size n, cc_unit *r, const cc_unit *s, const cc_unit *t);
-
-/* r = gcd(s, t).
- N bit, N bit -> O bit */
-CC_NONNULL((2, 4, 6))
-void ccn_gcdn(cc_size rn, cc_unit *r, cc_size sn, const cc_unit *s, cc_size tn, const cc_unit *t);
-
/* r = (data, len) treated as a big endian byte array, return -1 if data
doesn't fit in r, return 0 otherwise. */
CC_NONNULL((2, 4))
int ccn_read_uint(cc_size n, cc_unit *r, size_t data_size, const uint8_t *data);
/* r = (data, len) treated as a big endian byte array, return -1 if data
- doesn't fit in r, return 0 otherwise.
+ doesn't fit in r, return 0 otherwise.
ccn_read_uint strips leading zeroes and doesn't care about sign. */
#define ccn_read_int(n, r, data_size, data) ccn_read_uint(n, r, data_size, data)
/* Return actual size in bytes needed to serialize s. */
-CC_PURE CC_NONNULL2
+CC_PURE CC_NONNULL((2))
size_t ccn_write_uint_size(cc_size n, const cc_unit *s);
/* Serialize s, to out.
}
-/* Return actual size in bytes needed to serialize s as int
+/* Return actual size in bytes needed to serialize s as int
(adding leading zero if high bit is set). */
-CC_PURE CC_NONNULL2
+CC_PURE CC_NONNULL((2))
size_t ccn_write_int_size(cc_size n, const cc_unit *s);
/* Serialize s, to out.
CC_NONNULL((2, 4))
void ccn_write_int(cc_size n, const cc_unit *s, size_t out_size, void *out);
-
-/* s^2 -> r
- { n bit -> 2 * n bit } */
-CC_INLINE CC_NONNULL((2, 3))
-void ccn_sqr(cc_size n, cc_unit *r, const cc_unit *s) {
- ccn_mul(n, r, s, s);
-}
-
/* s -> r
{ n bit -> n bit } */
CC_NONNULL((2, 3))
void ccn_set(cc_size n, cc_unit *r, const cc_unit *s);
-CC_INLINE CC_NONNULL2
+CC_INLINE CC_NONNULL((2))
void ccn_zero(cc_size n, cc_unit *r) {
- CC_BZERO(r, ccn_sizeof_n(n));
+ cc_zero(ccn_sizeof_n(n),r);
}
-CC_NONNULL2
-void ccn_zero_multi(cc_size n, cc_unit *r, ...);
+CC_INLINE CC_NONNULL((2))
+void ccn_clear(cc_size n, cc_unit *r) {
+ cc_clear(ccn_sizeof_n(n),r);
+}
-/* Burn (zero fill or otherwise overwrite) n cc_units of stack space. */
-void ccn_burn_stack(cc_size n);
+CC_NONNULL((2))
+void ccn_zero_multi(cc_size n, cc_unit *r, ...);
-CC_INLINE CC_NONNULL2
+CC_INLINE CC_NONNULL((2))
void ccn_seti(cc_size n, cc_unit *r, cc_unit v) {
/* assert(n > 0); */
r[0] = v;
#endif
/* Swap units in r in place from cc_unit vector byte order to big endian byte order (or back). */
-CC_INLINE CC_NONNULL2
+CC_INLINE CC_NONNULL((2))
void ccn_swap(cc_size n, cc_unit *r) {
cc_unit *e;
for (e = r + n - 1; r < e; ++r, --e) {
}
/* Debugging */
-CC_NONNULL2
+CC_NONNULL((2))
void ccn_print(cc_size n, const cc_unit *s);
-CC_NONNULL3
+CC_NONNULL((3))
void ccn_lprint(cc_size n, const char *label, const cc_unit *s);
/* Forward declaration so we don't depend on ccrng.h. */
CC_NONNULL((2, 3))
int ccn_random_bits(cc_size nbits, cc_unit *r, struct ccrng_state *rng);
+CC_NONNULL((6, 8))
+int ccn_div_euclid(cc_size nq, cc_unit *q, cc_size nr, cc_unit *r, cc_size na, const cc_unit *a, cc_size nd, const cc_unit *d);
+
+#define ccn_div(nq, q, na, a, nd, d) ccn_div_euclid(nq, q, 0, NULL, na, a, nd, d)
+#define ccn_mod(nr, r, na, a, nd, d) ccn_div_euclid(0 , NULL, nr, r, na, a, nd, d)
+
#endif /* _CORECRYPTO_CCN_H_ */