in crypto/cryptosoft.c [577:902]
int swcr_newsession(FAR uint32_t *sid, FAR struct cryptoini *cri)
{
FAR struct swcr_data **swd;
FAR const struct auth_hash *axf;
FAR const struct enc_xform *txf;
uint32_t i;
int k;
if (sid == NULL || cri == NULL)
{
return -EINVAL;
}
if (swcr_sessions)
{
for (i = 1; i < swcr_sesnum; i++)
{
if (swcr_sessions[i] == NULL)
{
break;
}
}
}
if (swcr_sessions == NULL || i == swcr_sesnum)
{
if (swcr_sessions == NULL)
{
i = 1; /* We leave swcr_sessions[0] empty */
swcr_sesnum = CRYPTO_SW_SESSIONS;
}
else
{
swcr_sesnum *= 2;
}
swd = kmm_calloc(swcr_sesnum, sizeof(struct swcr_data *));
if (swd == NULL)
{
/* Reset session number */
if (swcr_sesnum == CRYPTO_SW_SESSIONS)
{
swcr_sesnum = 0;
}
else
{
swcr_sesnum /= 2;
}
return -ENOBUFS;
}
/* Copy existing sessions */
if (swcr_sessions)
{
bcopy(swcr_sessions, swd,
(swcr_sesnum / 2) * sizeof(struct swcr_data *));
kmm_free(swcr_sessions);
}
swcr_sessions = swd;
}
swd = &swcr_sessions[i];
*sid = i;
while (cri)
{
*swd = kmm_zalloc(sizeof(struct swcr_data));
if (*swd == NULL)
{
swcr_freesession(i);
return -ENOBUFS;
}
switch (cri->cri_alg)
{
case CRYPTO_3DES_CBC:
txf = &enc_xform_3des;
goto enccommon;
case CRYPTO_BLF_CBC:
txf = &enc_xform_blf;
goto enccommon;
case CRYPTO_CAST_CBC:
txf = &enc_xform_cast5;
goto enccommon;
case CRYPTO_AES_CBC:
txf = &enc_xform_aes;
goto enccommon;
case CRYPTO_AES_CTR:
txf = &enc_xform_aes_ctr;
goto enccommon;
case CRYPTO_AES_XTS:
txf = &enc_xform_aes_xts;
goto enccommon;
case CRYPTO_AES_GCM_16:
txf = &enc_xform_aes_gcm;
goto enccommon;
case CRYPTO_AES_GMAC:
txf = &enc_xform_aes_gmac;
(*swd)->sw_exf = txf;
break;
case CRYPTO_AES_CMAC:
txf = &enc_xform_aes_cmac;
(*swd)->sw_exf = txf;
break;
case CRYPTO_AES_OFB:
txf = &enc_xform_aes_ofb;
goto enccommon;
case CRYPTO_AES_CFB_8:
txf = &enc_xform_aes_cfb_8;
goto enccommon;
case CRYPTO_AES_CFB_128:
txf = &enc_xform_aes_cfb_128;
goto enccommon;
case CRYPTO_CHACHA20_POLY1305:
txf = &enc_xform_chacha20_poly1305;
goto enccommon;
case CRYPTO_NULL:
txf = &enc_xform_null;
goto enccommon;
enccommon:
if (txf->ctxsize > 0)
{
(*swd)->sw_kschedule = kmm_zalloc(txf->ctxsize);
if ((*swd)->sw_kschedule == NULL)
{
swcr_freesession(i);
return -EINVAL;
}
}
if (cri->cri_klen / 8 > txf->maxkey ||
cri->cri_klen / 8 < txf->minkey)
{
swcr_freesession(i);
return -EINVAL;
}
if (txf->setkey((*swd)->sw_kschedule,
(FAR uint8_t *)cri->cri_key,
cri->cri_klen / 8) < 0)
{
swcr_freesession(i);
return -EINVAL;
}
(*swd)->sw_exf = txf;
break;
case CRYPTO_MD5_HMAC:
axf = &auth_hash_hmac_md5_96;
goto authcommon;
case CRYPTO_SHA1_HMAC:
axf = &auth_hash_hmac_sha1_96;
goto authcommon;
case CRYPTO_RIPEMD160_HMAC:
axf = &auth_hash_hmac_ripemd_160_96;
goto authcommon;
case CRYPTO_SHA2_256_HMAC:
axf = &auth_hash_hmac_sha2_256_128;
goto authcommon;
case CRYPTO_SHA2_384_HMAC:
axf = &auth_hash_hmac_sha2_384_192;
goto authcommon;
case CRYPTO_SHA2_512_HMAC:
axf = &auth_hash_hmac_sha2_512_256;
authcommon:
(*swd)->sw_ictx = kmm_malloc(axf->ctxsize);
if ((*swd)->sw_ictx == NULL)
{
swcr_freesession(i);
return -ENOBUFS;
}
(*swd)->sw_octx = kmm_malloc(axf->ctxsize);
if ((*swd)->sw_octx == NULL)
{
swcr_freesession(i);
return -ENOBUFS;
}
if (cri->cri_klen / 8 > axf->keysize)
{
swcr_freesession(i);
return -EINVAL;
}
for (k = 0; k < cri->cri_klen / 8; k++)
{
cri->cri_key[k] ^= HMAC_IPAD_VAL;
}
axf->init((*swd)->sw_ictx);
axf->update((*swd)->sw_ictx, (FAR uint8_t *)cri->cri_key,
cri->cri_klen / 8);
axf->update((*swd)->sw_ictx, hmac_ipad_buffer,
axf->blocksize - (cri->cri_klen / 8));
for (k = 0; k < cri->cri_klen / 8; k++)
{
cri->cri_key[k] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL);
}
axf->init((*swd)->sw_octx);
axf->update((*swd)->sw_octx, (FAR uint8_t *)cri->cri_key,
cri->cri_klen / 8);
axf->update((*swd)->sw_octx, hmac_opad_buffer,
axf->blocksize - (cri->cri_klen / 8));
for (k = 0; k < cri->cri_klen / 8; k++)
{
cri->cri_key[k] ^= HMAC_OPAD_VAL;
}
(*swd)->sw_axf = axf;
bcopy((*swd)->sw_ictx, &(*swd)->sw_ctx, axf->ctxsize);
break;
case CRYPTO_MD5:
axf = &auth_hash_md5;
goto auth3common;
case CRYPTO_RIPEMD160:
axf = &auth_hash_ripemd_160;
goto auth3common;
case CRYPTO_SHA1:
axf = &auth_hash_sha1;
goto auth3common;
case CRYPTO_SHA2_224:
axf = &auth_hash_sha2_224;
goto auth3common;
case CRYPTO_SHA2_256:
axf = &auth_hash_sha2_256;
goto auth3common;
case CRYPTO_SHA2_384:
axf = &auth_hash_sha2_384;
goto auth3common;
case CRYPTO_SHA2_512:
axf = &auth_hash_sha2_512;
auth3common:
(*swd)->sw_ictx = kmm_zalloc(axf->ctxsize);
if ((*swd)->sw_ictx == NULL)
{
swcr_freesession(i);
return -ENOBUFS;
}
axf->init((*swd)->sw_ictx);
(*swd)->sw_axf = axf;
bcopy((*swd)->sw_ictx, &(*swd)->sw_ctx, axf->ctxsize);
if (cri->cri_sid != -1)
{
if (swcr_sessions[cri->cri_sid] == NULL)
{
swcr_freesession(i);
return -EINVAL;
}
bcopy(&swcr_sessions[cri->cri_sid]->sw_ctx, &(*swd)->sw_ctx,
axf->ctxsize);
}
break;
case CRYPTO_AES_128_GMAC:
axf = &auth_hash_gmac_aes_128;
goto auth4common;
case CRYPTO_AES_192_GMAC:
axf = &auth_hash_gmac_aes_192;
goto auth4common;
case CRYPTO_AES_256_GMAC:
axf = &auth_hash_gmac_aes_256;
goto auth4common;
case CRYPTO_AES_128_CMAC:
axf = &auth_hash_cmac_aes_128;
goto auth4common;
case CRYPTO_POLY1305:
axf = &auth_hash_poly1305;
goto auth4common;
case CRYPTO_CRC32:
axf = &auth_hash_crc32;
goto auth4common;
case CRYPTO_CHACHA20_POLY1305_MAC:
axf = &auth_hash_chacha20_poly1305;
auth4common:
(*swd)->sw_ictx = kmm_malloc(axf->ctxsize);
if ((*swd)->sw_ictx == NULL)
{
swcr_freesession(i);
return -ENOBUFS;
}
axf->init((*swd)->sw_ictx);
axf->setkey((*swd)->sw_ictx, (FAR uint8_t *)cri->cri_key,
cri->cri_klen / 8);
bcopy((*swd)->sw_ictx, &(*swd)->sw_ctx, axf->ctxsize);
(*swd)->sw_axf = axf;
break;
case CRYPTO_ESN:
/* nothing to do */
break;
default:
swcr_freesession(i);
return -EINVAL;
}
(*swd)->sw_alg = cri->cri_alg;
cri = cri->cri_next;
swd = &((*swd)->sw_next);
}
return 0;
}