mirror of
https://github.com/apache/nuttx.git
synced 2026-08-01 20:28:58 +00:00
crypto: add CRYPTO_AES_CTR_SSH variant (128-bit big-endian counter)
The existing CRYPTO_AES_CTR is the RFC 3686 profile: the last 4 bytes of the key are a nonce, the IV is 8 bytes and only the low 32 bits of the counter block are incremented. SSH aes128/192/256-ctr (RFC 4344) instead uses the key as-is (no embedded nonce) and treats the whole 16-byte IV as the initial counter block, incremented as a 128-bit big-endian integer, with the first keystream block being E(IV). Add CRYPTO_AES_CTR_SSH as a new enc_xform mirroring the CRYPTO_CHACHA20_DJB addition. It reuses struct aes_ctr_ctx and the AES block; only setkey (full key, no nonce), reinit (full 16-byte counter) and crypt (encrypt-then- increment over all 16 bytes) differ from the RFC 3686 variant. Keystream validated against `openssl enc -aes-128-ctr`, including a counter that carries across byte boundaries and a non-block-aligned tail. Signed-off-by: Felipe Moura <moura.fmo@gmail.com>
This commit is contained in:
parent
cbe4ceb158
commit
ce645060fa
5 changed files with 78 additions and 1 deletions
|
|
@ -232,6 +232,7 @@ static int cryptof_ioctl(FAR struct file *filep,
|
|||
case CRYPTO_AES_256_CBC:
|
||||
case CRYPTO_AES_CMAC:
|
||||
case CRYPTO_AES_CTR:
|
||||
case CRYPTO_AES_CTR_SSH:
|
||||
case CRYPTO_AES_XTS:
|
||||
case CRYPTO_AES_OFB:
|
||||
case CRYPTO_AES_CFB_8:
|
||||
|
|
|
|||
|
|
@ -1619,6 +1619,9 @@ int swcr_newsession(FAR uint32_t *sid, FAR struct cryptoini *cri)
|
|||
case CRYPTO_AES_CTR:
|
||||
txf = &enc_xform_aes_ctr;
|
||||
goto enccommon;
|
||||
case CRYPTO_AES_CTR_SSH:
|
||||
txf = &enc_xform_aes_ctr_ssh;
|
||||
goto enccommon;
|
||||
case CRYPTO_AES_XTS:
|
||||
txf = &enc_xform_aes_xts;
|
||||
goto enccommon;
|
||||
|
|
@ -1903,6 +1906,7 @@ int swcr_freesession(uint64_t tid)
|
|||
case CRYPTO_CAST_CBC:
|
||||
case CRYPTO_RIJNDAEL128_CBC:
|
||||
case CRYPTO_AES_CTR:
|
||||
case CRYPTO_AES_CTR_SSH:
|
||||
case CRYPTO_AES_XTS:
|
||||
case CRYPTO_AES_GCM_16:
|
||||
case CRYPTO_AES_GMAC:
|
||||
|
|
@ -2046,6 +2050,7 @@ int swcr_process(struct cryptop *crp)
|
|||
case CRYPTO_CAST_CBC:
|
||||
case CRYPTO_RIJNDAEL128_CBC:
|
||||
case CRYPTO_AES_CTR:
|
||||
case CRYPTO_AES_CTR_SSH:
|
||||
case CRYPTO_AES_XTS:
|
||||
case CRYPTO_AES_OFB:
|
||||
case CRYPTO_AES_CFB_8:
|
||||
|
|
@ -2442,6 +2447,7 @@ void swcr_init(void)
|
|||
algs[CRYPTO_RIPEMD160_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
|
||||
algs[CRYPTO_RIJNDAEL128_CBC] = CRYPTO_ALG_FLAG_SUPPORTED;
|
||||
algs[CRYPTO_AES_CTR] = CRYPTO_ALG_FLAG_SUPPORTED;
|
||||
algs[CRYPTO_AES_CTR_SSH] = CRYPTO_ALG_FLAG_SUPPORTED;
|
||||
algs[CRYPTO_AES_XTS] = CRYPTO_ALG_FLAG_SUPPORTED;
|
||||
algs[CRYPTO_AES_GCM_16] = CRYPTO_ALG_FLAG_SUPPORTED;
|
||||
algs[CRYPTO_AES_GMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ int blf_setkey(FAR void *, FAR uint8_t *, int);
|
|||
int cast5_setkey(FAR void *, FAR uint8_t *, int);
|
||||
int aes_setkey_xform(FAR void *, FAR uint8_t *, int);
|
||||
int aes_ctr_setkey(FAR void *, FAR uint8_t *, int);
|
||||
int aes_ctr_ssh_setkey(FAR void *, FAR uint8_t *, int);
|
||||
int aes_xts_setkey(FAR void *, FAR uint8_t *, int);
|
||||
int aes_ofb_setkey(FAR void *, FAR uint8_t *, int);
|
||||
int null_setkey(FAR void *, FAR uint8_t *, int);
|
||||
|
|
@ -132,8 +133,10 @@ void aes_cfb8_decrypt(caddr_t, FAR uint8_t *, size_t);
|
|||
void aes_cfb128_decrypt(caddr_t, FAR uint8_t *, size_t);
|
||||
|
||||
void aes_ctr_crypt(caddr_t, FAR uint8_t *, size_t);
|
||||
void aes_ctr_ssh_crypt(caddr_t, FAR uint8_t *, size_t);
|
||||
|
||||
void aes_ctr_reinit(caddr_t, FAR uint8_t *);
|
||||
void aes_ctr_ssh_reinit(caddr_t, FAR uint8_t *);
|
||||
void aes_xts_reinit(caddr_t, FAR uint8_t *);
|
||||
void aes_gcm_reinit(caddr_t, FAR uint8_t *);
|
||||
void aes_ofb_reinit(caddr_t, FAR uint8_t *);
|
||||
|
|
@ -232,6 +235,17 @@ const struct enc_xform enc_xform_aes_ctr =
|
|||
aes_ctr_reinit
|
||||
};
|
||||
|
||||
const struct enc_xform enc_xform_aes_ctr_ssh =
|
||||
{
|
||||
CRYPTO_AES_CTR_SSH, "AES-CTR-SSH",
|
||||
16, 16, 16, 32,
|
||||
sizeof(struct aes_ctr_ctx),
|
||||
aes_ctr_ssh_crypt,
|
||||
aes_ctr_ssh_crypt,
|
||||
aes_ctr_ssh_setkey,
|
||||
aes_ctr_ssh_reinit
|
||||
};
|
||||
|
||||
const struct enc_xform enc_xform_aes_gcm =
|
||||
{
|
||||
CRYPTO_AES_GCM_16, "AES-GCM",
|
||||
|
|
@ -697,6 +711,60 @@ int aes_ctr_setkey(FAR void *sched, FAR uint8_t *key, int len)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* SSH AES-CTR (RFC 4344). Unlike the RFC 3686 variant above, the key holds
|
||||
* no embedded nonce and the whole 16-byte IV is the initial counter block,
|
||||
* incremented as a 128-bit big-endian integer. The counter is encrypted
|
||||
* before it is incremented so the first block keystream is E(IV).
|
||||
*/
|
||||
|
||||
void aes_ctr_ssh_crypt(caddr_t key, FAR uint8_t *data, size_t len)
|
||||
{
|
||||
FAR struct aes_ctr_ctx *ctx;
|
||||
uint8_t keystream[AESCTR_BLOCKSIZE];
|
||||
int i;
|
||||
|
||||
ctx = (FAR struct aes_ctr_ctx *)key;
|
||||
|
||||
aes_encrypt(&ctx->ac_key, ctx->ac_block, keystream);
|
||||
for (i = 0; i < AESCTR_BLOCKSIZE; i++)
|
||||
{
|
||||
data[i] ^= keystream[i];
|
||||
}
|
||||
|
||||
/* increment the 128-bit big-endian counter */
|
||||
|
||||
for (i = AESCTR_BLOCKSIZE - 1; i >= 0; i--)
|
||||
{
|
||||
if (++ctx->ac_block[i])
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
explicit_bzero(keystream, sizeof(keystream));
|
||||
}
|
||||
|
||||
int aes_ctr_ssh_setkey(FAR void *sched, FAR uint8_t *key, int len)
|
||||
{
|
||||
FAR struct aes_ctr_ctx *ctx;
|
||||
|
||||
ctx = (FAR struct aes_ctr_ctx *)sched;
|
||||
if (aes_setkey(&ctx->ac_key, key, len) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void aes_ctr_ssh_reinit(caddr_t key, FAR uint8_t *iv)
|
||||
{
|
||||
FAR struct aes_ctr_ctx *ctx;
|
||||
|
||||
ctx = (FAR struct aes_ctr_ctx *)key;
|
||||
bcopy(iv, ctx->ac_block, AESCTR_BLOCKSIZE);
|
||||
}
|
||||
|
||||
void aes_xts_reinit(caddr_t key, FAR uint8_t *iv)
|
||||
{
|
||||
FAR struct aes_xts_ctx *ctx = (FAR struct aes_xts_ctx *)key;
|
||||
|
|
|
|||
|
|
@ -142,7 +142,8 @@
|
|||
#define CRYPTO_SHA2_224_HMAC 41
|
||||
#define CRYPTO_CHACHA20 42
|
||||
#define CRYPTO_CHACHA20_DJB 43
|
||||
#define CRYPTO_ALGORITHM_MAX 43 /* Keep updated */
|
||||
#define CRYPTO_AES_CTR_SSH 44
|
||||
#define CRYPTO_ALGORITHM_MAX 44 /* Keep updated */
|
||||
|
||||
/* Algorithm flags */
|
||||
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ extern const struct enc_xform enc_xform_blf;
|
|||
extern const struct enc_xform enc_xform_cast5;
|
||||
extern const struct enc_xform enc_xform_aes;
|
||||
extern const struct enc_xform enc_xform_aes_ctr;
|
||||
extern const struct enc_xform enc_xform_aes_ctr_ssh;
|
||||
extern const struct enc_xform enc_xform_aes_gcm;
|
||||
extern const struct enc_xform enc_xform_aes_gmac;
|
||||
extern const struct enc_xform enc_xform_aes_cmac;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue