summaryrefslogtreecommitdiff
path: root/cpp/src/polo/pairing/polochallengeresponse.cc
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src/polo/pairing/polochallengeresponse.cc')
-rw-r--r--cpp/src/polo/pairing/polochallengeresponse.cc147
1 files changed, 147 insertions, 0 deletions
diff --git a/cpp/src/polo/pairing/polochallengeresponse.cc b/cpp/src/polo/pairing/polochallengeresponse.cc
new file mode 100644
index 0000000..7ef52ca
--- /dev/null
+++ b/cpp/src/polo/pairing/polochallengeresponse.cc
@@ -0,0 +1,147 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// This class performs several computations on the client and server public keys
+// to generate and verify challenge hashes.
+
+#include "polo/pairing/polochallengeresponse.h"
+
+#include <glog/logging.h>
+#include "polo/util/poloutil.h"
+
+namespace polo {
+namespace pairing {
+
+PoloChallengeResponse::PoloChallengeResponse(X509* client_cert,
+ X509* server_cert)
+ : client_cert(client_cert),
+ server_cert(server_cert) {
+}
+
+Alpha* PoloChallengeResponse::GetAlpha(const Nonce& nonce) const {
+ EVP_PKEY* client_pkey = X509_get_pubkey(client_cert);
+ if (!client_pkey) {
+ return NULL;
+ }
+
+ RSA* client_pub_rsa = EVP_PKEY_get1_RSA(client_pkey);
+ if (!client_pub_rsa) {
+ return NULL;
+ }
+
+ EVP_PKEY* server_pkey = X509_get_pubkey(server_cert);
+ if (!server_pkey) {
+ return NULL;
+ }
+
+ RSA* server_pub_rsa = EVP_PKEY_get1_RSA(server_pkey);
+ if (!server_pub_rsa) {
+ return NULL;
+ }
+
+ // Compute a hash of the concatenated public keys. The client and server
+ // modulus and exponent are concatenated along with the random nonce then a
+ // SHA256 hash is computed on the result.
+ size_t client_modulus_size = BN_num_bytes(client_pub_rsa->n);
+ size_t client_exponent_size = BN_num_bytes(client_pub_rsa->e);
+
+ size_t server_modulus_size = BN_num_bytes(server_pub_rsa->n);
+ size_t server_exponent_size = BN_num_bytes(server_pub_rsa->e);
+
+ size_t buffer_size = client_modulus_size + client_exponent_size
+ + server_modulus_size + server_exponent_size
+ + nonce.size();
+
+ uint8_t* buffer = new unsigned char[buffer_size];
+ uint8_t* pos = buffer;
+
+ BN_bn2bin(client_pub_rsa->n, pos);
+ pos += client_modulus_size;
+
+ BN_bn2bin(client_pub_rsa->e, pos);
+ pos += client_exponent_size;
+
+ BN_bn2bin(server_pub_rsa->n, pos);
+ pos += server_modulus_size;
+
+ BN_bn2bin(server_pub_rsa->e, pos);
+ pos += server_exponent_size;
+
+ memcpy(pos, &nonce[0], nonce.size());
+
+ Alpha* alpha = new Alpha(SHA256_DIGEST_LENGTH);
+ SHA256(buffer, buffer_size, &(*alpha)[0]);
+ delete[] buffer;
+
+ RSA_free(client_pub_rsa);
+ EVP_PKEY_free(client_pkey);
+
+ RSA_free(server_pub_rsa);
+ EVP_PKEY_free(server_pkey);
+
+ return alpha;
+}
+
+Gamma* PoloChallengeResponse::GetGamma(const Nonce& nonce) const {
+ const Alpha* alpha = GetAlpha(nonce);
+ if (!alpha) {
+ return NULL;
+ }
+
+ Gamma* gamma = new Gamma(nonce.size() * 2);
+
+ if (alpha->size() >= nonce.size()) {
+ memcpy(&(*gamma)[0], &(*alpha)[0], nonce.size());
+ memcpy(&(*gamma)[nonce.size()], &nonce[0], nonce.size());
+ }
+ delete alpha;
+
+ return gamma;
+}
+
+Nonce* PoloChallengeResponse::ExtractNonce(const Gamma& gamma) const {
+ if ((gamma.size() < 2) || (gamma.size() % 2 != 0)) {
+ return NULL;
+ }
+
+ Nonce* nonce = new Nonce(gamma.size() / 2);
+ memcpy(&(*nonce)[0], &gamma[nonce->size()], nonce->size());
+
+ return nonce;
+}
+
+bool PoloChallengeResponse::CheckGamma(const Gamma& gamma) const {
+ const Nonce* nonce = ExtractNonce(gamma);
+
+ if (!nonce) {
+ return false;
+ }
+
+ const Gamma* expected = GetGamma(*nonce);
+
+ LOG(INFO) << "CheckGamma expected: "
+ << util::PoloUtil::BytesToHexString(&(*expected)[0], expected->size())
+ << " actual: "
+ << util::PoloUtil::BytesToHexString(&gamma[0], gamma.size());
+
+ bool check = (gamma == (*expected));
+
+ delete nonce;
+ delete expected;
+
+ return check;
+}
+
+} // namespace pairing
+} // namespace polo