Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of wolfSSL by
chacha20_poly1305.c
00001 /* chacha.c 00002 * 00003 * Copyright (C) 2006-2016 wolfSSL Inc. 00004 * 00005 * This file is part of wolfSSL. 00006 * 00007 * wolfSSL is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 2 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * wolfSSL is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA 00020 */ 00021 00022 00023 00024 #ifdef HAVE_CONFIG_H 00025 #include <config.h> 00026 #endif 00027 00028 #include <wolfssl/wolfcrypt/settings.h> 00029 00030 #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) 00031 00032 #include <wolfssl/wolfcrypt/chacha20_poly1305.h> 00033 #include <wolfssl/wolfcrypt/error-crypt.h> 00034 #include <wolfssl/wolfcrypt/logging.h> 00035 #include <wolfssl/wolfcrypt/chacha.h> 00036 #include <wolfssl/wolfcrypt/poly1305.h> 00037 00038 #ifdef NO_INLINE 00039 #include <wolfssl/wolfcrypt/misc.h> 00040 #else 00041 #define WOLFSSL_MISC_INCLUDED 00042 #include <wolfcrypt/src/misc.c> 00043 #endif 00044 00045 #ifdef CHACHA_AEAD_TEST 00046 #include <stdio.h> 00047 #endif 00048 00049 #define CHACHA20_POLY1305_AEAD_INITIAL_COUNTER 0 00050 #define CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT 16 00051 00052 static void word32ToLittle64(const word32 inLittle32, byte outLittle64[8]); 00053 static int calculateAuthTag( 00054 const byte inAuthKey[CHACHA20_POLY1305_AEAD_KEYSIZE], 00055 const byte* inAAD, const word32 inAADLen, 00056 const byte *inCiphertext, const word32 inCiphertextLen, 00057 byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]); 00058 00059 int wc_ChaCha20Poly1305_Encrypt( 00060 const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE], 00061 const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE], 00062 const byte* inAAD, const word32 inAADLen, 00063 const byte* inPlaintext, const word32 inPlaintextLen, 00064 byte* outCiphertext, 00065 byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]) 00066 { 00067 int err; 00068 byte poly1305Key[CHACHA20_POLY1305_AEAD_KEYSIZE]; 00069 ChaCha chaChaCtx; 00070 00071 /* Validate function arguments */ 00072 00073 if (!inKey || !inIV || 00074 !inPlaintext || !inPlaintextLen || 00075 !outCiphertext || 00076 !outAuthTag) 00077 { 00078 return BAD_FUNC_ARG; 00079 } 00080 00081 XMEMSET(poly1305Key, 0, sizeof(poly1305Key)); 00082 00083 /* Create the Poly1305 key */ 00084 err = wc_Chacha_SetKey(&chaChaCtx, inKey, CHACHA20_POLY1305_AEAD_KEYSIZE); 00085 if (err != 0) return err; 00086 00087 err = wc_Chacha_SetIV(&chaChaCtx, inIV, 00088 CHACHA20_POLY1305_AEAD_INITIAL_COUNTER); 00089 if (err != 0) return err; 00090 00091 err = wc_Chacha_Process(&chaChaCtx, poly1305Key, poly1305Key, 00092 CHACHA20_POLY1305_AEAD_KEYSIZE); 00093 if (err != 0) return err; 00094 00095 /* Encrypt the plaintext using ChaCha20 */ 00096 err = wc_Chacha_Process(&chaChaCtx, outCiphertext, inPlaintext, 00097 inPlaintextLen); 00098 /* Calculate the Poly1305 auth tag */ 00099 if (err == 0) 00100 err = calculateAuthTag(poly1305Key, 00101 inAAD, inAADLen, 00102 outCiphertext, inPlaintextLen, 00103 outAuthTag); 00104 ForceZero(poly1305Key, sizeof(poly1305Key)); 00105 00106 return err; 00107 } 00108 00109 00110 int wc_ChaCha20Poly1305_Decrypt( 00111 const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE], 00112 const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE], 00113 const byte* inAAD, const word32 inAADLen, 00114 const byte* inCiphertext, const word32 inCiphertextLen, 00115 const byte inAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE], 00116 byte* outPlaintext) 00117 { 00118 int err; 00119 byte poly1305Key[CHACHA20_POLY1305_AEAD_KEYSIZE]; 00120 ChaCha chaChaCtx; 00121 byte calculatedAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]; 00122 00123 /* Validate function arguments */ 00124 00125 if (!inKey || !inIV || 00126 !inCiphertext || !inCiphertextLen || 00127 !inAuthTag || 00128 !outPlaintext) 00129 { 00130 return BAD_FUNC_ARG; 00131 } 00132 00133 XMEMSET(calculatedAuthTag, 0, sizeof(calculatedAuthTag)); 00134 XMEMSET(poly1305Key, 0, sizeof(poly1305Key)); 00135 00136 /* Create the Poly1305 key */ 00137 err = wc_Chacha_SetKey(&chaChaCtx, inKey, CHACHA20_POLY1305_AEAD_KEYSIZE); 00138 if (err != 0) return err; 00139 00140 err = wc_Chacha_SetIV(&chaChaCtx, inIV, 00141 CHACHA20_POLY1305_AEAD_INITIAL_COUNTER); 00142 if (err != 0) return err; 00143 00144 err = wc_Chacha_Process(&chaChaCtx, poly1305Key, poly1305Key, 00145 CHACHA20_POLY1305_AEAD_KEYSIZE); 00146 if (err != 0) return err; 00147 00148 /* Calculate the Poly1305 auth tag */ 00149 err = calculateAuthTag(poly1305Key, 00150 inAAD, inAADLen, 00151 inCiphertext, inCiphertextLen, 00152 calculatedAuthTag); 00153 00154 /* Compare the calculated auth tag with the received one */ 00155 if (err == 0 && ConstantCompare(inAuthTag, calculatedAuthTag, 00156 CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE) != 0) 00157 { 00158 err = MAC_CMP_FAILED_E; 00159 } 00160 00161 /* Decrypt the received ciphertext */ 00162 if (err == 0) 00163 err = wc_Chacha_Process(&chaChaCtx, outPlaintext, inCiphertext, 00164 inCiphertextLen); 00165 ForceZero(poly1305Key, sizeof(poly1305Key)); 00166 00167 return err; 00168 } 00169 00170 00171 static int calculateAuthTag( 00172 const byte inAuthKey[CHACHA20_POLY1305_AEAD_KEYSIZE], 00173 const byte *inAAD, const word32 inAADLen, 00174 const byte *inCiphertext, const word32 inCiphertextLen, 00175 byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]) 00176 { 00177 int err; 00178 Poly1305 poly1305Ctx; 00179 byte padding[CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT - 1]; 00180 word32 paddingLen; 00181 byte little64[8]; 00182 00183 XMEMSET(padding, 0, sizeof(padding)); 00184 00185 /* Initialize Poly1305 */ 00186 00187 err = wc_Poly1305SetKey(&poly1305Ctx, inAuthKey, 00188 CHACHA20_POLY1305_AEAD_KEYSIZE); 00189 if (err) 00190 { 00191 return err; 00192 } 00193 00194 /* Create the authTag by MAC'ing the following items: */ 00195 00196 /* -- AAD */ 00197 00198 if (inAAD && inAADLen) 00199 { 00200 err = wc_Poly1305Update(&poly1305Ctx, inAAD, inAADLen); 00201 00202 /* -- padding1: pad the AAD to 16 bytes */ 00203 00204 paddingLen = -(int)inAADLen & (CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT - 1); 00205 if (paddingLen) 00206 { 00207 err += wc_Poly1305Update(&poly1305Ctx, padding, paddingLen); 00208 } 00209 00210 if (err) 00211 { 00212 return err; 00213 } 00214 } 00215 00216 /* -- Ciphertext */ 00217 00218 err = wc_Poly1305Update(&poly1305Ctx, inCiphertext, inCiphertextLen); 00219 if (err) 00220 { 00221 return err; 00222 } 00223 00224 /* -- padding2: pad the ciphertext to 16 bytes */ 00225 00226 paddingLen = -(int)inCiphertextLen & 00227 (CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT - 1); 00228 if (paddingLen) 00229 { 00230 err = wc_Poly1305Update(&poly1305Ctx, padding, paddingLen); 00231 if (err) 00232 { 00233 return err; 00234 } 00235 } 00236 00237 /* -- AAD length as a 64-bit little endian integer */ 00238 00239 word32ToLittle64(inAADLen, little64); 00240 00241 err = wc_Poly1305Update(&poly1305Ctx, little64, sizeof(little64)); 00242 if (err) 00243 { 00244 return err; 00245 } 00246 00247 /* -- Ciphertext length as a 64-bit little endian integer */ 00248 00249 word32ToLittle64(inCiphertextLen, little64); 00250 00251 err = wc_Poly1305Update(&poly1305Ctx, little64, sizeof(little64)); 00252 if (err) 00253 { 00254 return err; 00255 } 00256 00257 /* Finalize the auth tag */ 00258 00259 err = wc_Poly1305Final(&poly1305Ctx, outAuthTag); 00260 00261 return err; 00262 } 00263 00264 00265 static void word32ToLittle64(const word32 inLittle32, byte outLittle64[8]) 00266 { 00267 XMEMSET(outLittle64, 0, 8); 00268 00269 outLittle64[0] = (byte)(inLittle32 & 0x000000FF); 00270 outLittle64[1] = (byte)((inLittle32 & 0x0000FF00) >> 8); 00271 outLittle64[2] = (byte)((inLittle32 & 0x00FF0000) >> 16); 00272 outLittle64[3] = (byte)((inLittle32 & 0xFF000000) >> 24); 00273 } 00274 00275 00276 #endif /* HAVE_CHACHA && HAVE_POLY1305 */ 00277
Generated on Tue Jul 12 2022 23:30:54 by
 1.7.2 
    