polochallengeresponse.cc revision 7c9978567a202d6aa98beac5da5e1b3b34792862
1// Copyright 2012 Google Inc. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15// This class performs several computations on the client and server public keys
16// to generate and verify challenge hashes.
17
18#include "polo/pairing/polochallengeresponse.h"
19
20#include <glog/logging.h>
21#include "polo/util/poloutil.h"
22
23namespace polo {
24namespace pairing {
25
26PoloChallengeResponse::PoloChallengeResponse(X509* client_cert,
27                                             X509* server_cert)
28    : client_cert(client_cert),
29      server_cert(server_cert) {
30}
31
32Alpha* PoloChallengeResponse::GetAlpha(const Nonce& nonce) const {
33  EVP_PKEY* client_pkey = X509_get_pubkey(client_cert);
34  if (!client_pkey) {
35    return NULL;
36  }
37
38  RSA* client_pub_rsa = EVP_PKEY_get1_RSA(client_pkey);
39  if (!client_pub_rsa) {
40    return NULL;
41  }
42
43  EVP_PKEY* server_pkey = X509_get_pubkey(server_cert);
44  if (!server_pkey) {
45    return NULL;
46  }
47
48  RSA* server_pub_rsa = EVP_PKEY_get1_RSA(server_pkey);
49  if (!server_pub_rsa) {
50    return NULL;
51  }
52
53  // Compute a hash of the concatenated public keys. The client and server
54  // modulus and exponent are concatenated along with the random nonce then a
55  // SHA256 hash is computed on the result.
56  size_t client_modulus_size = BN_num_bytes(client_pub_rsa->n);
57  size_t client_exponent_size = BN_num_bytes(client_pub_rsa->e);
58
59  size_t server_modulus_size = BN_num_bytes(server_pub_rsa->n);
60  size_t server_exponent_size = BN_num_bytes(server_pub_rsa->e);
61
62  size_t buffer_size = client_modulus_size + client_exponent_size
63            + server_modulus_size + server_exponent_size
64            + nonce.size();
65
66  uint8_t* buffer = new unsigned char[buffer_size];
67  uint8_t* pos = buffer;
68
69  BN_bn2bin(client_pub_rsa->n, pos);
70  pos += client_modulus_size;
71
72  BN_bn2bin(client_pub_rsa->e, pos);
73  pos += client_exponent_size;
74
75  BN_bn2bin(server_pub_rsa->n, pos);
76  pos += server_modulus_size;
77
78  BN_bn2bin(server_pub_rsa->e, pos);
79  pos += server_exponent_size;
80
81  memcpy(pos, &nonce[0], nonce.size());
82
83  Alpha* alpha = new Alpha(SHA256_DIGEST_LENGTH);
84  SHA256(buffer, buffer_size, &(*alpha)[0]);
85  delete[] buffer;
86
87  RSA_free(client_pub_rsa);
88  EVP_PKEY_free(client_pkey);
89
90  RSA_free(server_pub_rsa);
91  EVP_PKEY_free(server_pkey);
92
93  return alpha;
94}
95
96Gamma* PoloChallengeResponse::GetGamma(const Nonce& nonce) const {
97  const Alpha* alpha = GetAlpha(nonce);
98  if (!alpha) {
99    return NULL;
100  }
101
102  Gamma* gamma = new Gamma(nonce.size() * 2);
103
104  if (alpha->size() >= nonce.size()) {
105    memcpy(&(*gamma)[0], &(*alpha)[0], nonce.size());
106    memcpy(&(*gamma)[nonce.size()], &nonce[0], nonce.size());
107  }
108  delete alpha;
109
110  return gamma;
111}
112
113Nonce* PoloChallengeResponse::ExtractNonce(const Gamma& gamma) const {
114  if ((gamma.size() < 2) || (gamma.size() % 2 != 0)) {
115    return NULL;
116  }
117
118  Nonce* nonce = new Nonce(gamma.size() / 2);
119  memcpy(&(*nonce)[0], &gamma[nonce->size()], nonce->size());
120
121  return nonce;
122}
123
124bool PoloChallengeResponse::CheckGamma(const Gamma& gamma) const {
125  const Nonce* nonce = ExtractNonce(gamma);
126
127  if (!nonce) {
128    return false;
129  }
130
131  const Gamma* expected = GetGamma(*nonce);
132
133  LOG(INFO) << "CheckGamma expected: "
134      << util::PoloUtil::BytesToHexString(&(*expected)[0], expected->size())
135      << " actual: "
136      << util::PoloUtil::BytesToHexString(&gamma[0], gamma.size());
137
138  bool check = (gamma == (*expected));
139
140  delete nonce;
141  delete expected;
142
143  return check;
144}
145
146}  // namespace pairing
147}  // namespace polo
148