static void aead_cipher_ctx_set_key(cipher_ctx_t *cipher_ctx, int enc) { const digest_type_t *md = mbedtls_md_info_from_string("SHA1"); if (md == NULL) { FATAL("SHA1 Digest not found in crypto library"); } int err = crypto_hkdf(md, cipher_ctx->salt, cipher_ctx->cipher->key_len, cipher_ctx->cipher->key, cipher_ctx->cipher->key_len, (uint8_t *)SUBKEY_INFO, strlen(SUBKEY_INFO), cipher_ctx->skey, cipher_ctx->cipher->key_len); if (err) { FATAL("Unable to generate subkey"); } memset(cipher_ctx->nonce, 0, cipher_ctx->cipher->nonce_len); /* cipher that don't use mbed TLS, just return */ if (cipher_ctx->cipher->method >= CHACHA20POLY1305IETF) { return; } if (mbedtls_cipher_setkey(cipher_ctx->evp, cipher_ctx->skey, cipher_ctx->cipher->key_len * 8, enc) != 0) { FATAL("Cannot set mbed TLS cipher key"); } if (mbedtls_cipher_reset(cipher_ctx->evp) != 0) { FATAL("Cannot finish preparation of mbed TLS cipher context"); } }
int CipherContext::setKey(State & state, mbedtls_cipher_context_t * context){ Stack * stack = state.stack; if (stack->is<LUA_TSTRING>(1) && stack->is<LUA_TNUMBER>(2)){ const std::string key = stack->toLString(1); int bitLen = key.length() * 8; mbedtls_operation_t operation = static_cast<mbedtls_operation_t>(stack->to<int>(2)); stack->push<int>(mbedtls_cipher_setkey(context, reinterpret_cast<const unsigned char*>(key.c_str()), bitLen, operation)); return 1; } return 0; }
static int cipher_set_encrypt_key_cbc(struct ssh_cipher_struct *cipher, void *key, void *IV) { const mbedtls_cipher_info_t *cipher_info = NULL; int rc; mbedtls_cipher_init(&cipher->encrypt_ctx); cipher_info = mbedtls_cipher_info_from_type(cipher->type); rc = mbedtls_cipher_setup(&cipher->encrypt_ctx, cipher_info); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_setup failed"); goto error; } rc = mbedtls_cipher_setkey(&cipher->encrypt_ctx, key, cipher_info->key_bitlen, MBEDTLS_ENCRYPT); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_setkey failed"); goto error; } rc = mbedtls_cipher_set_iv(&cipher->encrypt_ctx, IV, cipher_info->iv_size); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_set_iv failed"); goto error; } /* libssh only encypts and decrypts packets that are multiples of a block * size, and no padding is used */ rc = mbedtls_cipher_set_padding_mode(&cipher->encrypt_ctx, MBEDTLS_PADDING_NONE); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_set_padding_mode failed"); goto error; } rc = mbedtls_cipher_reset(&cipher->encrypt_ctx); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_reset failed"); goto error; } return SSH_OK; error: mbedtls_cipher_free(&cipher->encrypt_ctx); return SSH_ERROR; }
void cipher_ctx_set_nonce(cipher_ctx_t *cipher_ctx, uint8_t *nonce, size_t nonce_len, int enc) { const unsigned char *true_key; cipher_t *cipher = cipher_ctx->cipher; if (nonce == NULL) { LOGE("cipher_ctx_set_nonce(): NONCE is null"); return; } if (cipher->method >= SALSA20) { return; } if (cipher->method == RC4_MD5) { unsigned char key_nonce[32]; memcpy(key_nonce, cipher->key, 16); memcpy(key_nonce + 16, nonce, 16); true_key = crypto_md5(key_nonce, 32, NULL); nonce_len = 0; } else { true_key = cipher->key; } cipher_evp_t *evp = cipher_ctx->evp; if (evp == NULL) { LOGE("cipher_ctx_set_nonce(): Cipher context is null"); return; } if (mbedtls_cipher_setkey(evp, true_key, cipher->key_len * 8, enc) != 0) { mbedtls_cipher_free(evp); FATAL("Cannot set mbed TLS cipher key"); } if (mbedtls_cipher_set_iv(evp, nonce, nonce_len) != 0) { mbedtls_cipher_free(evp); FATAL("Cannot set mbed TLS cipher NONCE"); } if (mbedtls_cipher_reset(evp) != 0) { mbedtls_cipher_free(evp); FATAL("Cannot finalize mbed TLS cipher context"); } #ifdef SS_DEBUG dump("NONCE", (char *)nonce, nonce_len); dump("KEY", (char *)true_key, 32); #endif }
result_t Cipher::process(const mbedtls_operation_t operation, Buffer_base *data, obj_ptr<Buffer_base> &retVal) { int32_t ret; ret = mbedtls_cipher_setkey(&m_ctx, (unsigned char *)m_key.c_str(), (int32_t)m_key.length() * 8, operation); if (ret != 0) return CHECK_ERROR(_ssl::setError(ret)); ret = mbedtls_cipher_reset(&m_ctx); if (ret != 0) return CHECK_ERROR(_ssl::setError(ret)); exlib::string input; exlib::string output; unsigned char buffer[1024]; size_t olen, ilen, offset, block_size, data_size; data->toString(input); block_size = mbedtls_cipher_get_block_size(&m_ctx); data_size = input.length(); for (offset = 0; offset < data_size; offset += block_size) { ilen = ((uint32_t)data_size - offset > block_size) ? block_size : (uint32_t)(data_size - offset); ret = mbedtls_cipher_update(&m_ctx, (unsigned char *)input.c_str() + offset, ilen, buffer, &olen); if (ret != 0) { reset(); return CHECK_ERROR(_ssl::setError(ret)); } output.append((const char *)buffer, olen); } ret = mbedtls_cipher_finish(&m_ctx, buffer, &olen); reset(); if (ret != 0) return CHECK_ERROR(_ssl::setError(ret)); output.append((const char *)buffer, olen); retVal = new Buffer(output); return 0; }
static int cipher_set_decrypt_key_cbc(struct ssh_cipher_struct *cipher, void *key, void *IV) { const mbedtls_cipher_info_t *cipher_info; int rc; mbedtls_cipher_init(&cipher->decrypt_ctx); cipher_info = mbedtls_cipher_info_from_type(cipher->type); rc = mbedtls_cipher_setup(&cipher->decrypt_ctx, cipher_info); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_setkey failed"); goto error; } rc = mbedtls_cipher_setkey(&cipher->decrypt_ctx, key, cipher_info->key_bitlen, MBEDTLS_DECRYPT); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_setkey failed"); goto error; } rc = mbedtls_cipher_set_iv(&cipher->decrypt_ctx, IV, cipher_info->iv_size); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_set_iv failed"); goto error; } rc = mbedtls_cipher_set_padding_mode(&cipher->decrypt_ctx, MBEDTLS_PADDING_NONE); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_set_padding_mode failed"); goto error; } mbedtls_cipher_reset(&cipher->decrypt_ctx); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_reset failed"); goto error; } return SSH_OK; error: mbedtls_cipher_free(&cipher->decrypt_ctx); return SSH_ERROR; }
int mbedtls_nist_kw_setkey( mbedtls_nist_kw_context *ctx, mbedtls_cipher_id_t cipher, const unsigned char *key, unsigned int keybits, const int is_wrap ) { int ret; const mbedtls_cipher_info_t *cipher_info; cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB ); if( cipher_info == NULL ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); if( cipher_info->block_size != 16 ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); /* * SP 800-38F currently defines AES cipher as the only block cipher allowed: * "For KW and KWP, the underlying block cipher shall be approved, and the * block size shall be 128 bits. Currently, the AES block cipher, with key * lengths of 128, 192, or 256 bits, is the only block cipher that fits * this profile." * Currently we don't support other 128 bit block ciphers for key wrapping, * such as Camellia and Aria. */ if( cipher != MBEDTLS_CIPHER_ID_AES ) return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); mbedtls_cipher_free( &ctx->cipher_ctx ); if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) return( ret ); if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, is_wrap ? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT ) ) != 0 ) { return( ret ); } return( 0 ); }
static int cipher_set_encrypt_key(struct ssh_cipher_struct *cipher, void *key, void *IV) { const mbedtls_cipher_info_t *cipher_info = NULL; int rc; mbedtls_cipher_init(&cipher->encrypt_ctx); cipher_info = mbedtls_cipher_info_from_type(cipher->type); rc = mbedtls_cipher_setup(&cipher->encrypt_ctx, cipher_info); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_setup failed"); goto error; } rc = mbedtls_cipher_setkey(&cipher->encrypt_ctx, key, cipher_info->key_bitlen, MBEDTLS_ENCRYPT); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_setkey failed"); goto error; } rc = mbedtls_cipher_set_iv(&cipher->encrypt_ctx, IV, cipher_info->iv_size); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_set_iv failed"); goto error; } rc = mbedtls_cipher_reset(&cipher->encrypt_ctx); if (rc != 0) { SSH_LOG(SSH_LOG_WARNING, "mbedtls_cipher_reset failed"); goto error; } return SSH_OK; error: mbedtls_cipher_free(&cipher->encrypt_ctx); return SSH_ERROR; }
void cipher_ctx_init(mbedtls_cipher_context_t *ctx, const uint8_t *key, int key_len, const mbedtls_cipher_info_t *kt, const mbedtls_operation_t operation) { ASSERT(NULL != kt && NULL != ctx); CLEAR(*ctx); if (!mbed_ok(mbedtls_cipher_setup(ctx, kt))) { msg(M_FATAL, "mbed TLS cipher context init #1"); } if (!mbed_ok(mbedtls_cipher_setkey(ctx, key, key_len*8, operation))) { msg(M_FATAL, "mbed TLS cipher set key"); } /* make sure we used a big enough key */ ASSERT(ctx->key_bitlen <= key_len*8); }
void cipher_context_set_iv(cipher_ctx_t *ctx, uint8_t *iv, size_t iv_len, int enc) { const unsigned char *true_key; if (iv == NULL) { LOGE("cipher_context_set_iv(): IV is null"); return; } if (!enc) { memcpy(ctx->iv, iv, iv_len); } if (enc_method >= SALSA20) { return; } if (enc_method == RC4_MD5) { unsigned char key_iv[32]; memcpy(key_iv, enc_key, 16); memcpy(key_iv + 16, iv, 16); true_key = enc_md5(key_iv, 32, NULL); iv_len = 0; } else { true_key = enc_key; } #ifdef USE_CRYPTO_APPLECC cipher_cc_t *cc = &ctx->cc; if (cc->valid == kCCContextValid) { memcpy(cc->iv, iv, iv_len); memcpy(cc->key, true_key, enc_key_len); cc->iv_len = iv_len; cc->key_len = enc_key_len; cc->encrypt = enc ? kCCEncrypt : kCCDecrypt; if (cc->cryptor != NULL) { CCCryptorRelease(cc->cryptor); cc->cryptor = NULL; } CCCryptorStatus ret; ret = CCCryptorCreateWithMode( cc->encrypt, cc->mode, cc->cipher, cc->padding, cc->iv, cc->key, cc->key_len, NULL, 0, 0, 0, &cc->cryptor); if (ret != kCCSuccess) { if (cc->cryptor != NULL) { CCCryptorRelease(cc->cryptor); cc->cryptor = NULL; } FATAL("Cannot set CommonCrypto key and IV"); } return; } #endif cipher_evp_t *evp = &ctx->evp; if (evp == NULL) { LOGE("cipher_context_set_iv(): Cipher context is null"); return; } #if defined(USE_CRYPTO_OPENSSL) if (!EVP_CipherInit_ex(evp, NULL, NULL, true_key, iv, enc)) { EVP_CIPHER_CTX_cleanup(evp); FATAL("Cannot set key and IV"); } #elif defined(USE_CRYPTO_POLARSSL) // XXX: PolarSSL 1.3.11: cipher_free_ctx deprecated, Use cipher_free() instead. if (cipher_setkey(evp, true_key, enc_key_len * 8, enc) != 0) { cipher_free_ctx(evp); FATAL("Cannot set PolarSSL cipher key"); } #if POLARSSL_VERSION_NUMBER >= 0x01030000 if (cipher_set_iv(evp, iv, iv_len) != 0) { cipher_free_ctx(evp); FATAL("Cannot set PolarSSL cipher IV"); } if (cipher_reset(evp) != 0) { cipher_free_ctx(evp); FATAL("Cannot finalize PolarSSL cipher context"); } #else if (cipher_reset(evp, iv) != 0) { cipher_free_ctx(evp); FATAL("Cannot set PolarSSL cipher IV"); } #endif #elif defined(USE_CRYPTO_MBEDTLS) if (mbedtls_cipher_setkey(evp, true_key, enc_key_len * 8, enc) != 0) { mbedtls_cipher_free(evp); FATAL("Cannot set mbed TLS cipher key"); } if (mbedtls_cipher_set_iv(evp, iv, iv_len) != 0) { mbedtls_cipher_free(evp); FATAL("Cannot set mbed TLS cipher IV"); } if (mbedtls_cipher_reset(evp) != 0) { mbedtls_cipher_free(evp); FATAL("Cannot finalize mbed TLS cipher context"); } #endif #ifdef DEBUG dump("IV", (char *)iv, iv_len); #endif }
int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode, const unsigned char *pwd, size_t pwdlen, const unsigned char *data, size_t datalen, unsigned char *output ) { int ret, iterations = 0, keylen = 0; unsigned char *p, *end; mbedtls_asn1_buf kdf_alg_oid, enc_scheme_oid, kdf_alg_params, enc_scheme_params; mbedtls_asn1_buf salt; mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1; unsigned char key[32], iv[32]; size_t olen = 0; const mbedtls_md_info_t *md_info; const mbedtls_cipher_info_t *cipher_info; mbedtls_md_context_t md_ctx; mbedtls_cipher_type_t cipher_alg; mbedtls_cipher_context_t cipher_ctx; p = pbe_params->p; end = p + pbe_params->len; /* * PBES2-params ::= SEQUENCE { * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} * } */ if( pbe_params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); if( ( ret = mbedtls_asn1_get_alg( &p, end, &kdf_alg_oid, &kdf_alg_params ) ) != 0 ) return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); // Only PBKDF2 supported at the moment // if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBKDF2, &kdf_alg_oid ) != 0 ) return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); if( ( ret = pkcs5_parse_pbkdf2_params( &kdf_alg_params, &salt, &iterations, &keylen, &md_type ) ) != 0 ) { return( ret ); } md_info = mbedtls_md_info_from_type( md_type ); if( md_info == NULL ) return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); if( ( ret = mbedtls_asn1_get_alg( &p, end, &enc_scheme_oid, &enc_scheme_params ) ) != 0 ) { return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); } if( mbedtls_oid_get_cipher_alg( &enc_scheme_oid, &cipher_alg ) != 0 ) return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); cipher_info = mbedtls_cipher_info_from_type( cipher_alg ); if( cipher_info == NULL ) return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); /* * The value of keylen from pkcs5_parse_pbkdf2_params() is ignored * since it is optional and we don't know if it was set or not */ keylen = cipher_info->key_bitlen / 8; if( enc_scheme_params.tag != MBEDTLS_ASN1_OCTET_STRING || enc_scheme_params.len != cipher_info->iv_size ) { return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT ); } mbedtls_md_init( &md_ctx ); mbedtls_cipher_init( &cipher_ctx ); memcpy( iv, enc_scheme_params.p, enc_scheme_params.len ); if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) goto exit; if( ( ret = mbedtls_pkcs5_pbkdf2_hmac( &md_ctx, pwd, pwdlen, salt.p, salt.len, iterations, keylen, key ) ) != 0 ) { goto exit; } if( ( ret = mbedtls_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 ) goto exit; if( ( ret = mbedtls_cipher_setkey( &cipher_ctx, key, 8 * keylen, (mbedtls_operation_t) mode ) ) != 0 ) goto exit; if( ( ret = mbedtls_cipher_crypt( &cipher_ctx, iv, enc_scheme_params.len, data, datalen, output, &olen ) ) != 0 ) ret = MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH; exit: mbedtls_md_free( &md_ctx ); mbedtls_cipher_free( &cipher_ctx ); return( ret ); }