/* chronyd/chronyc - Programs for keeping computer clocks accurate. ********************************************************************** * Copyright (C) Miroslav Lichvar 2019 * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ********************************************************************** ======================================================================= SIV ciphers using the Nettle library */ #include "config.h" #include "sysincl.h" #ifdef HAVE_NETTLE_SIV_CMAC #include #else #include "siv_nettle_int.c" #endif #include "memory.h" #include "siv.h" struct SIV_Instance_Record { struct siv_cmac_aes128_ctx siv; int key_set; }; /* ================================================== */ SIV_Instance SIV_CreateInstance(SIV_Algorithm algorithm) { SIV_Instance instance; if (algorithm != AEAD_AES_SIV_CMAC_256) return NULL; instance = MallocNew(struct SIV_Instance_Record); instance->key_set = 0; return instance; } /* ================================================== */ void SIV_DestroyInstance(SIV_Instance instance) { Free(instance); } /* ================================================== */ int SIV_GetKeyLength(SIV_Algorithm algorithm) { assert(32 <= SIV_MAX_KEY_LENGTH); if (algorithm == AEAD_AES_SIV_CMAC_256) return 32; return 0; } /* ================================================== */ int SIV_SetKey(SIV_Instance instance, const unsigned char *key, int length) { if (length != 32) return 0; siv_cmac_aes128_set_key(&instance->siv, key); instance->key_set = 1; return 1; } /* ================================================== */ int SIV_GetTagLength(SIV_Instance instance) { assert(SIV_DIGEST_SIZE <= SIV_MAX_TAG_LENGTH); return SIV_DIGEST_SIZE; } /* ================================================== */ int SIV_Encrypt(SIV_Instance instance, const unsigned char *nonce, int nonce_length, const void *assoc, int assoc_length, const void *plaintext, int plaintext_length, unsigned char *ciphertext, int ciphertext_length) { if (!instance->key_set) return 0; if (nonce_length < SIV_MIN_NONCE_SIZE || assoc_length < 0 || plaintext_length < 0 || plaintext_length > ciphertext_length || plaintext_length + SIV_DIGEST_SIZE != ciphertext_length) return 0; assert(assoc && plaintext); siv_cmac_aes128_encrypt_message(&instance->siv, nonce_length, nonce, assoc_length, assoc, ciphertext_length, ciphertext, plaintext); return 1; } /* ================================================== */ int SIV_Decrypt(SIV_Instance instance, const unsigned char *nonce, int nonce_length, const void *assoc, int assoc_length, const unsigned char *ciphertext, int ciphertext_length, void *plaintext, int plaintext_length) { if (!instance->key_set) return 0; if (nonce_length < SIV_MIN_NONCE_SIZE || assoc_length < 0 || plaintext_length < 0 || plaintext_length > ciphertext_length || plaintext_length + SIV_DIGEST_SIZE != ciphertext_length) return 0; assert(assoc && plaintext); if (!siv_cmac_aes128_decrypt_message(&instance->siv, nonce_length, nonce, assoc_length, assoc, plaintext_length, plaintext, ciphertext)) return 0; return 1; }