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.
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 #include <wolfcrypt/src/misc.c> 00042 #endif 00043 00044 #ifdef CHACHA_AEAD_TEST 00045 #include <stdio.h> 00046 #endif 00047 00048 #define CHACHA20_POLY1305_AEAD_INITIAL_COUNTER 0 00049 #define CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT 16 00050 00051 static void word32ToLittle64(const word32 inLittle32, byte outLittle64[8]); 00052 static int calculateAuthTag( 00053 const byte inAuthKey[CHACHA20_POLY1305_AEAD_KEYSIZE], 00054 const byte* inAAD, const word32 inAADLen, 00055 const byte *inCiphertext, const word32 inCiphertextLen, 00056 byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]); 00057 00058 int wc_ChaCha20Poly1305_Encrypt( 00059 const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE], 00060 const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE], 00061 const byte* inAAD, const word32 inAADLen, 00062 const byte* inPlaintext, const word32 inPlaintextLen, 00063 byte* outCiphertext, 00064 byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]) 00065 { 00066 int err; 00067 byte poly1305Key[CHACHA20_POLY1305_AEAD_KEYSIZE]; 00068 ChaCha chaChaCtx; 00069 00070 /* Validate function arguments */ 00071 00072 if (!inKey || !inIV || 00073 !inPlaintext || !inPlaintextLen || 00074 !outCiphertext || 00075 !outAuthTag) 00076 { 00077 return BAD_FUNC_ARG; 00078 } 00079 00080 XMEMSET(poly1305Key, 0, sizeof(poly1305Key)); 00081 00082 /* Create the Poly1305 key */ 00083 err = wc_Chacha_SetKey(&chaChaCtx, inKey, CHACHA20_POLY1305_AEAD_KEYSIZE); 00084 if (err != 0) return err; 00085 00086 err = wc_Chacha_SetIV(&chaChaCtx, inIV, 00087 CHACHA20_POLY1305_AEAD_INITIAL_COUNTER); 00088 if (err != 0) return err; 00089 00090 err = wc_Chacha_Process(&chaChaCtx, poly1305Key, poly1305Key, 00091 CHACHA20_POLY1305_AEAD_KEYSIZE); 00092 if (err != 0) return err; 00093 00094 /* Encrypt the plaintext using ChaCha20 */ 00095 err = wc_Chacha_Process(&chaChaCtx, outCiphertext, inPlaintext, 00096 inPlaintextLen); 00097 /* Calculate the Poly1305 auth tag */ 00098 if (err == 0) 00099 err = calculateAuthTag(poly1305Key, 00100 inAAD, inAADLen, 00101 outCiphertext, inPlaintextLen, 00102 outAuthTag); 00103 ForceZero(poly1305Key, sizeof(poly1305Key)); 00104 00105 return err; 00106 } 00107 00108 00109 int wc_ChaCha20Poly1305_Decrypt( 00110 const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE], 00111 const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE], 00112 const byte* inAAD, const word32 inAADLen, 00113 const byte* inCiphertext, const word32 inCiphertextLen, 00114 const byte inAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE], 00115 byte* outPlaintext) 00116 { 00117 int err; 00118 byte poly1305Key[CHACHA20_POLY1305_AEAD_KEYSIZE]; 00119 ChaCha chaChaCtx; 00120 byte calculatedAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]; 00121 00122 /* Validate function arguments */ 00123 00124 if (!inKey || !inIV || 00125 !inCiphertext || !inCiphertextLen || 00126 !inAuthTag || 00127 !outPlaintext) 00128 { 00129 return BAD_FUNC_ARG; 00130 } 00131 00132 XMEMSET(calculatedAuthTag, 0, sizeof(calculatedAuthTag)); 00133 XMEMSET(poly1305Key, 0, sizeof(poly1305Key)); 00134 00135 /* Create the Poly1305 key */ 00136 err = wc_Chacha_SetKey(&chaChaCtx, inKey, CHACHA20_POLY1305_AEAD_KEYSIZE); 00137 if (err != 0) return err; 00138 00139 err = wc_Chacha_SetIV(&chaChaCtx, inIV, 00140 CHACHA20_POLY1305_AEAD_INITIAL_COUNTER); 00141 if (err != 0) return err; 00142 00143 err = wc_Chacha_Process(&chaChaCtx, poly1305Key, poly1305Key, 00144 CHACHA20_POLY1305_AEAD_KEYSIZE); 00145 if (err != 0) return err; 00146 00147 /* Calculate the Poly1305 auth tag */ 00148 err = calculateAuthTag(poly1305Key, 00149 inAAD, inAADLen, 00150 inCiphertext, inCiphertextLen, 00151 calculatedAuthTag); 00152 00153 /* Compare the calculated auth tag with the received one */ 00154 if (err == 0 && ConstantCompare(inAuthTag, calculatedAuthTag, 00155 CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE) != 0) 00156 { 00157 err = MAC_CMP_FAILED_E; 00158 } 00159 00160 /* Decrypt the received ciphertext */ 00161 if (err == 0) 00162 err = wc_Chacha_Process(&chaChaCtx, outPlaintext, inCiphertext, 00163 inCiphertextLen); 00164 ForceZero(poly1305Key, sizeof(poly1305Key)); 00165 00166 return err; 00167 } 00168 00169 00170 static int calculateAuthTag( 00171 const byte inAuthKey[CHACHA20_POLY1305_AEAD_KEYSIZE], 00172 const byte *inAAD, const word32 inAADLen, 00173 const byte *inCiphertext, const word32 inCiphertextLen, 00174 byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]) 00175 { 00176 int err; 00177 Poly1305 poly1305Ctx; 00178 byte padding[CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT - 1]; 00179 word32 paddingLen; 00180 byte little64[8]; 00181 00182 XMEMSET(padding, 0, sizeof(padding)); 00183 00184 /* Initialize Poly1305 */ 00185 00186 err = wc_Poly1305SetKey(&poly1305Ctx, inAuthKey, 00187 CHACHA20_POLY1305_AEAD_KEYSIZE); 00188 if (err) 00189 { 00190 return err; 00191 } 00192 00193 /* Create the authTag by MAC'ing the following items: */ 00194 00195 /* -- AAD */ 00196 00197 if (inAAD && inAADLen) 00198 { 00199 err = wc_Poly1305Update(&poly1305Ctx, inAAD, inAADLen); 00200 00201 /* -- padding1: pad the AAD to 16 bytes */ 00202 00203 paddingLen = -(int)inAADLen & (CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT - 1); 00204 if (paddingLen) 00205 { 00206 err += wc_Poly1305Update(&poly1305Ctx, padding, paddingLen); 00207 } 00208 00209 if (err) 00210 { 00211 return err; 00212 } 00213 } 00214 00215 /* -- Ciphertext */ 00216 00217 err = wc_Poly1305Update(&poly1305Ctx, inCiphertext, inCiphertextLen); 00218 if (err) 00219 { 00220 return err; 00221 } 00222 00223 /* -- padding2: pad the ciphertext to 16 bytes */ 00224 00225 paddingLen = -(int)inCiphertextLen & 00226 (CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT - 1); 00227 if (paddingLen) 00228 { 00229 err = wc_Poly1305Update(&poly1305Ctx, padding, paddingLen); 00230 if (err) 00231 { 00232 return err; 00233 } 00234 } 00235 00236 /* -- AAD length as a 64-bit little endian integer */ 00237 00238 word32ToLittle64(inAADLen, little64); 00239 00240 err = wc_Poly1305Update(&poly1305Ctx, little64, sizeof(little64)); 00241 if (err) 00242 { 00243 return err; 00244 } 00245 00246 /* -- Ciphertext length as a 64-bit little endian integer */ 00247 00248 word32ToLittle64(inCiphertextLen, little64); 00249 00250 err = wc_Poly1305Update(&poly1305Ctx, little64, sizeof(little64)); 00251 if (err) 00252 { 00253 return err; 00254 } 00255 00256 /* Finalize the auth tag */ 00257 00258 err = wc_Poly1305Final(&poly1305Ctx, outAuthTag); 00259 00260 return err; 00261 } 00262 00263 00264 static void word32ToLittle64(const word32 inLittle32, byte outLittle64[8]) 00265 { 00266 XMEMSET(outLittle64, 0, 8); 00267 00268 outLittle64[0] = (byte)(inLittle32 & 0x000000FF); 00269 outLittle64[1] = (byte)((inLittle32 & 0x0000FF00) >> 8); 00270 outLittle64[2] = (byte)((inLittle32 & 0x00FF0000) >> 16); 00271 outLittle64[3] = (byte)((inLittle32 & 0xFF000000) >> 24); 00272 } 00273 00274 00275 #endif /* HAVE_CHACHA && HAVE_POLY1305 */ 00276
Generated on Tue Jul 12 2022 15:55:18 by
1.7.2