/** 暗号化されたメッセージを複号する * @param[in] peer_addr 送信先IPアドレス * @param[in] message 暗号化するメッセージ * @param[out] ret_str 暗号化したメッセージを指すポインタ変数のアドレス * @param[out] len 暗号化メッセージ長返却領域 * @retval 0 正常終了 * @retval -EINVAL 引数異常 * @retval -EAGAIN 署名異常 */ int ipmsg_decrypt_message(const char *peer_addr, const char *message, unsigned char **ret_str, size_t *len) { int rc = 0; unsigned long this_cap = 0; unsigned char *hex_skey = NULL; char *skey = NULL; unsigned char *signed_message = NULL; unsigned char *end_message_body_p = NULL; unsigned char *enc_message = NULL; unsigned char *hex_sign = NULL; unsigned long skey_type = 0, akey_type = 0; unsigned long sign_type = 0; unsigned char *enc_bin_body = NULL; unsigned char *peer_key_e = NULL; unsigned char *peer_key_n = NULL; unsigned long tmp_cap = 0; unsigned long new_flags = 0; char *plain = NULL; size_t plain_len = 0; size_t skey_len = 0; size_t enc_bin_len = 0; if ( (message == NULL) || (ret_str == NULL) || (len == NULL) ) { rc = -EINVAL; goto error_out; } /* * 暗号化されたメッセージから鍵情報を獲得する. */ rc = parse_encrypted_message(message, &this_cap, &hex_skey, &enc_message, &hex_sign); if (rc != 0) { err_out("Can not parse message\n"); goto error_out; } /* * 暗号化に使用した鍵種別をケイパビリティから算出する */ skey_type = get_symkey_part(this_cap); /* 共通鍵 */ akey_type = get_asymkey_part(this_cap); /* 公開鍵 */ sign_type = get_sign_part(this_cap); /* 署名 */ dbg_out("Cap:%x Skey:%x AKey:%x Sign:%x\n", this_cap, skey_type, akey_type, sign_type); /* * 署名がある場合は署名を検証 */ g_assert(peer_addr); /* udpからの呼出しの場合はかならずいれる */ if ( (hostinfo_get_ipmsg_crypt_capability() & sign_type) && (hex_sign != NULL) ) { dbg_out("This message is signed by peer.\n"); /* * 相手の公開鍵を取得 */ rc = userdb_get_public_key_by_addr(peer_addr, &tmp_cap, (char **)&peer_key_e, (char **)&peer_key_n); if (rc != 0) { goto free_parsed_datas; } /* 編集用にコピー */ signed_message = g_strdup(message); rc = -ENOMEM; if (signed_message == NULL) goto free_parsed_datas; end_message_body_p = strrchr(signed_message, ':'); if (end_message_body_p == NULL) /* 異常データ */ goto free_parsed_datas; *end_message_body_p = '\0'; /* 本文だけを参照 */ dbg_out("Verify:%s with %s\n", signed_message, hex_sign); rc = pcrypt_verify_sign(this_cap, sign_type, signed_message, hex_sign, peer_key_e, peer_key_n); /* 失敗した場合でも, 不要なデータを開放してからぬける */ if (rc != 0) { err_out("Verify failed: libcrypt rc=%d\n", rc); rc = -EAGAIN; goto free_parsed_datas; } dbg_out("Verify OK\n"); } /* * 共通鍵をデコード */ /* FIXME 鍵のバリデーション(RSAが2つ以上設定されていないか) */ rc = pcrypt_decrypt_message(akey_type, hex_skey, &skey, &skey_len); if (rc != 0) { goto free_parsed_datas; } dbg_out("Decrypt key len:%d\n", skey_len); /* * 暗号化された本文のバイナリ化 */ rc = string_hex2bin(enc_message, &enc_bin_len, &enc_bin_body); if (rc != 0) { goto free_skey; } #if 0 print_hex(skey, skey_len); #endif /* * 本文を復号化する */ rc = symcrypt_decrypt_message(skey_type, enc_bin_body, enc_bin_len, skey, &plain, &plain_len); if (rc != 0) { goto free_enc_bin_body; } dbg_out("Decoded:%s len=%d\n", plain, plain_len); *ret_str = plain; *len = plain_len; rc = 0; free_enc_bin_body: if (enc_bin_body != NULL) g_free(enc_bin_body); free_skey: if (skey != NULL) g_free(skey); free_parsed_datas: if (hex_skey != NULL) g_free(hex_skey); if (enc_message != NULL) g_free(enc_message); if (hex_sign != NULL) g_free(hex_sign); if (peer_key_e != NULL) g_free(peer_key_e); if (peer_key_n != NULL) g_free(peer_key_n); if (signed_message != NULL) g_free(signed_message); error_out: if ( (rc != 0) && (rc != -EAGAIN) ){ /* 署名検証に失敗した場合を除く */ ipmsg_err_dialog("%s: %s = %s, rc = %d", _("Can not decode message"), _("peer"), peer_addr, rc); } return rc; }
String StringUtil::HexDecode(CStrRef input) { if (input.empty()) return input; int len = input.size(); char *ret = string_hex2bin(input.data(), len); return String(ret, len, AttachString); }