/* En/Decrypting a block requires use of the first 32 bytes of the block to provide salt. The next 64 bytes constitute a message authentication code (MAC) that is used to verify the validity of the block. The verification occurs in a higher level function, and all we need to know here is that we shouldn't decrypt the first 96 bytes of the block. */ int keyring_munge_block(unsigned char *block,int len /* includes the first 96 bytes */, unsigned char *KeyRingSalt,int KeyRingSaltLen, const char *KeyRingPin, const char *PKRPin) { int exit_code=1; unsigned char hashKey[crypto_hash_sha512_BYTES]; unsigned char hashNonce[crypto_hash_sha512_BYTES]; unsigned char work[65536]; int ofs; if (len<96) return WHY("block too short"); unsigned char *PKRSalt=&block[0]; int PKRSaltLen=32; #if crypto_stream_xsalsa20_KEYBYTES>crypto_hash_sha512_BYTES #error crypto primitive key size too long -- hash needs to be expanded #endif #if crypto_stream_xsalsa20_NONCEBYTES>crypto_hash_sha512_BYTES #error crypto primitive nonce size too long -- hash needs to be expanded #endif /* Generate key and nonce hashes from the various inputs */ #define APPEND(b,l) if (ofs+(l)>=65536) { WHY("Input too long"); goto kmb_safeexit; } bcopy((b),&work[ofs],(l)); ofs+=(l) /* Form key as hash of various concatenated inputs. The ordering and repetition of the inputs is designed to make rainbow tables infeasible */ ofs=0; APPEND(PKRSalt,PKRSaltLen); APPEND(PKRPin,strlen(PKRPin)); APPEND(PKRSalt,PKRSaltLen); APPEND(KeyRingPin,strlen(KeyRingPin)); crypto_hash_sha512(hashKey,work,ofs); /* Form the nonce as hash of various other concatenated inputs */ ofs=0; APPEND(KeyRingPin,strlen(KeyRingPin)); APPEND(KeyRingSalt,KeyRingSaltLen); APPEND(KeyRingPin,strlen(KeyRingPin)); APPEND(PKRPin,strlen(PKRPin)); crypto_hash_sha512(hashNonce,work,ofs); /* Now en/de-crypt the remainder of the block. We do this in-place for convenience, so you should not pass in a mmap()'d lump. */ crypto_stream_xsalsa20_xor(&block[96],&block[96],len-96, hashNonce,hashKey); exit_code=0; kmb_safeexit: /* Wipe out all sensitive structures before returning */ ofs=0; bzero(&work[0],65536); bzero(&hashKey[0],crypto_hash_sha512_BYTES); bzero(&hashNonce[0],crypto_hash_sha512_BYTES); return exit_code; #undef APPEND }
int crypto_stream_xor(unsigned char *c, const unsigned char *m, uint64_t mlen, const unsigned char *n, const unsigned char *k) { return crypto_stream_xsalsa20_xor(c, m, mlen, n, k); }
SODIUM_EXPORT int crypto_stream_xsalsa20_ref_xor(unsigned char *c, const unsigned char *m, unsigned long long mlen, const unsigned char *n, const unsigned char *k) { return crypto_stream_xsalsa20_xor(c, m, mlen, n, k); }
int crypto_secretbox( unsigned char *c, const unsigned char *m,unsigned long long mlen, const unsigned char *n, const unsigned char *k ) { int i; if (mlen < 32) return -1; crypto_stream_xsalsa20_xor(c,m,mlen,n,k); crypto_onetimeauth_poly1305(c + 16,c + 32,mlen - 32,c); for (i = 0;i < 16;++i) c[i] = 0; return 0; }
int crypto_secretbox_open( unsigned char *m, const unsigned char *c,unsigned long long clen, const unsigned char *n, const unsigned char *k ) { int i; unsigned char subkey[32]; if (clen < 32) return -1; crypto_stream_xsalsa20(subkey,32,n,k); if (crypto_onetimeauth_poly1305_verify(c + 16,c + 32,clen - 32,subkey) != 0) return -1; crypto_stream_xsalsa20_xor(m,c,clen,n,k); for (i = 0;i < 32;++i) m[i] = 0; return 0; }
int crypto_secretbox_xsalsa20poly1305_open( unsigned char *m, const unsigned char *c,crypto_uint16 clen, const unsigned char *n, const unsigned char *k ) { int i; unsigned char x[32]; if (clen < 32) return -1; crypto_stream_xsalsa20(x,32,n,k); if (crypto_onetimeauth_poly1305_verify(c + 16,c + 32,clen - 32,x) != 0) return -1; crypto_stream_xsalsa20_xor(m,c,clen,n,k); for(i=0;i<32;i++) m[i] = 0; return 0; }