1/* 2 * ccdigest.h 3 * corecrypto 4 * 5 * Created by Michael Brouwer on 11/30/10. 6 * Copyright 2010,2011 Apple Inc. All rights reserved. 7 * 8 */ 9 10#ifndef _CORECRYPTO_CCDIGEST_H_ 11#define _CORECRYPTO_CCDIGEST_H_ 12 13#include <corecrypto/cc.h> 14#include <corecrypto/ccn.h> 15 16/* To malloc a digest context for a given di, use malloc(ccdigest_di_size(di)) 17 and assign the result to a pointer to a struct ccdigest_ctx. */ 18struct ccdigest_ctx { 19 union { 20 uint8_t u8; 21 uint32_t u32; 22 uint64_t u64; 23 cc_unit ccn; 24 } state; 25} __attribute((aligned(8))); 26 27typedef union { 28 struct ccdigest_ctx *hdr; 29} ccdigest_ctx_t __attribute__((transparent_union)); 30 31struct ccdigest_state { 32 union { 33 uint8_t u8; 34 uint32_t u32; 35 uint64_t u64; 36 cc_unit ccn; 37 } state; 38} __attribute((aligned(8))); 39 40typedef union { 41 struct ccdigest_state *hdr; 42 struct ccdigest_ctx *_ctx; 43 ccdigest_ctx_t _ctxt; 44} ccdigest_state_t __attribute__((transparent_union)); 45 46struct ccdigest_info { 47 unsigned long output_size; 48 unsigned long state_size; 49 unsigned long block_size; 50 unsigned long oid_size; 51 unsigned char *oid; 52 const void *initial_state; 53 void(*compress)(ccdigest_state_t state, unsigned long nblocks, 54 const void *data); 55 void(*final)(const struct ccdigest_info *di, ccdigest_ctx_t ctx, 56 unsigned char *digest); 57}; 58 59/* Return sizeof a ccdigest_ctx for a given size_t _state_size_ and 60 size_t _block_size_. */ 61#define ccdigest_ctx_size(_state_size_, _block_size_) ((_state_size_) + sizeof(uint64_t) + (_block_size_) + sizeof(unsigned int)) 62/* Return sizeof a ccdigest_ctx for a given struct ccdigest_info *_di_. */ 63#define ccdigest_di_size(_di_) (ccdigest_ctx_size((_di_)->state_size, (_di_)->block_size)) 64 65/* Declare a ccdigest_ctx for a given size_t _state_size_ and 66 size_t _block_size_, named _name_. Can be used in structs or on the 67 stack. */ 68#define ccdigest_ctx_decl(_state_size_, _block_size_, _name_) cc_ctx_decl(struct ccdigest_ctx, ccdigest_ctx_size(_state_size_, _block_size_), _name_) 69#define ccdigest_ctx_clear(_state_size_, _block_size_, _name_) cc_ctx_clear(struct ccdigest_ctx, ccdigest_ctx_size(_state_size_, _block_size_), _name_) 70/* Declare a ccdigest_ctx for a given size_t _state_size_ and 71 size_t _block_size_, named _name_. Can be used on the stack. */ 72#define ccdigest_di_decl(_di_, _name_) cc_ctx_decl(struct ccdigest_ctx, ccdigest_di_size(_di_), _name_) 73#define ccdigest_di_clear(_di_, _name_) cc_ctx_clear(struct ccdigest_ctx, ccdigest_di_size(_di_), _name_) 74 75/* Digest context field accessors. Consider the implementation private. */ 76#define ccdigest_state(_di_, _ctx_) ((ccdigest_state_t)(_ctx_)) 77#define ccdigest_state_u8(_di_, _ctx_) (&((ccdigest_ctx_t)(_ctx_)).hdr->state.u8) 78#define ccdigest_state_u32(_di_, _ctx_) (&((ccdigest_ctx_t)(_ctx_)).hdr->state.u32) 79#define ccdigest_state_u64(_di_, _ctx_) (&((ccdigest_ctx_t)(_ctx_)).hdr->state.u64) 80#define ccdigest_state_ccn(_di_, _ctx_) (&((ccdigest_ctx_t)(_ctx_)).hdr->state.ccn) 81#define ccdigest_nbits(_di_, _ctx_) (((uint64_t *)(&((ccdigest_ctx_t)(_ctx_)).hdr->state.u8 + (_di_)->state_size))[0]) 82#define ccdigest_data(_di_, _ctx_) (&((ccdigest_ctx_t)(_ctx_)).hdr->state.u8 + (_di_)->state_size + sizeof(uint64_t)) 83#define ccdigest_num(_di_, _ctx_) (((unsigned int *)(&((ccdigest_ctx_t)(_ctx_)).hdr->state.u8 + (_di_)->state_size + sizeof(uint64_t) + (_di_)->block_size))[0]) 84 85/* Digest state field accessors. Consider the implementation private. */ 86#define ccdigest_u8(_state_) (&((ccdigest_state_t)(_state_)).hdr->state.u8) 87#define ccdigest_u32(_state_) (&((ccdigest_state_t)(_state_)).hdr->state.u32) 88#define ccdigest_u64(_state_) (&((ccdigest_state_t)(_state_)).hdr->state.u64) 89#define ccdigest_ccn(_state_) (&((ccdigest_state_t)(_state_)).hdr->state.ccn) 90 91/* We could just use memcpy instead of this special macro, but this allows us 92 to use the optimized ccn_set() assembly routine if we have one, which for 93 32 bit arm is about 200% quicker than generic memcpy(). */ 94#if CCN_SET_ASM && CCN_UNIT_SIZE <= 4 95#define ccdigest_copy_state(_di_, _dst_, _src_) ccn_set((_di_)->state_size / CCN_UNIT_SIZE, _dst_, _src_) 96#else 97#define ccdigest_copy_state(_di_, _dst_, _src_) CC_MEMCPY(_dst_, _src_, (_di_)->state_size) 98#endif 99 100void ccdigest_init(const struct ccdigest_info *di, ccdigest_ctx_t ctx); 101void ccdigest_update(const struct ccdigest_info *di, ccdigest_ctx_t ctx, 102 unsigned long len, const void *data); 103 104CC_INLINE 105void ccdigest_final(const struct ccdigest_info *di, ccdigest_ctx_t ctx, unsigned char *digest) 106{ 107 di->final(di,ctx,digest); 108} 109 110void ccdigest(const struct ccdigest_info *di, unsigned long len, 111 const void *data, void *digest); 112 113/* test functions */ 114int ccdigest_test(const struct ccdigest_info *di, unsigned long len, 115 const void *data, const void *digest); 116 117int ccdigest_test_chunk(const struct ccdigest_info *di, unsigned long len, 118 const void *data, const void *digest, unsigned long chunk); 119 120struct ccdigest_vector { 121 unsigned long len; 122 const void *message; 123 const void *digest; 124}; 125 126int ccdigest_test_vector(const struct ccdigest_info *di, const struct ccdigest_vector *v); 127int ccdigest_test_chunk_vector(const struct ccdigest_info *di, const struct ccdigest_vector *v, unsigned long chunk); 128 129#endif /* _CORECRYPTO_CCDIGEST_H_ */ 130