OLD | NEW |
| (Empty) |
1 // Copyright 2007-2009 Google Inc. | |
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 | |
16 #include "challenger.h" | |
17 | |
18 #include <stdlib.h> | |
19 #include <string.h> | |
20 #include <stdio.h> | |
21 | |
22 #include "rsa.h" | |
23 #include "md5.h" | |
24 #include "aes.h" | |
25 #include "b64.h" | |
26 | |
27 // Windows compilers do not have C99 support yet. | |
28 #if defined(WIN32) || defined(_WIN32) | |
29 #ifndef snprintf | |
30 #define snprintf _snprintf | |
31 #endif | |
32 #endif | |
33 | |
34 Challenger::Challenger(RSA::PublicKey pkey, | |
35 const unsigned char* seed, int seed_size) | |
36 : rsa_(pkey) { | |
37 memset(count_, 0, sizeof(count_)); | |
38 // Use seed as key for AES. Compress seed first. | |
39 MD5(seed, seed_size, seed_); | |
40 } | |
41 | |
42 const char* Challenger::challenge() { | |
43 uint8_t ctr[AES_BLOCK_SIZE]; | |
44 | |
45 // Compute current challenge. | |
46 AES_encrypt_block(seed_, count_, ctr); | |
47 | |
48 // Increment count for future fresh challenges. | |
49 for (size_t i = 0; i < sizeof(count_) && !++count_[i]; ++i); | |
50 | |
51 // Prepend our version number. | |
52 char* p = challenge_; | |
53 p += snprintf(challenge_, sizeof(challenge_), "%d:", rsa_.version()); | |
54 | |
55 // Append our current challenge. | |
56 B64_encode(ctr, sizeof(ctr), p, sizeof(challenge_) - (p - challenge_)); | |
57 | |
58 return challenge_; | |
59 } | |
60 | |
61 bool Challenger::verify(const char* hash, const char* signature) const { | |
62 char message[128]; | |
63 uint8_t sigbuf[128]; | |
64 | |
65 // Expect exactly 128 bytes of decoded signature data. | |
66 if (B64_decode(signature, sigbuf, sizeof(sigbuf)) != sizeof(sigbuf)) | |
67 return false; | |
68 | |
69 // Verify signature with baked-in public key and recover embedded message. | |
70 int result = rsa_.verify(sigbuf, sizeof(sigbuf), | |
71 message, sizeof(message) - 1); | |
72 | |
73 if (result < 0 || result >= static_cast<int>(sizeof(message) - 1)) | |
74 return false; | |
75 | |
76 // Since we're expecting a textual message, 0-terminate it. | |
77 message[result] = '\0'; | |
78 | |
79 // Construct and compare expected against received signed message. | |
80 char expected[128]; | |
81 snprintf(expected, sizeof(expected), "%s:%s", challenge_, hash); | |
82 | |
83 return !strcmp(expected, message); | |
84 } | |
OLD | NEW |