Ejemplo n.º 1
0
/** 暗号化されたメッセージを複号する
 *  @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;
}
Ejemplo n.º 2
0
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);
}