blob: d0c7a0d77eb50fe0ab6d3fc37cecc7883e69770d [file] [log] [blame]
David Zeuthen1eb12b22021-09-11 13:59:43 -04001/*
2 * Copyright 2020, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <inttypes.h>
18
19#include "EicCommon.h"
20#include "EicSession.h"
21
22// Global used for assigning ids for session objects.
23//
24static uint32_t gSessionLastIdAssigned = 0;
25
26// The current session object or NULL if never initialized or if it has been shut down.
27//
28static EicSession* gSessionCurrent = NULL;
29
30EicSession* eicSessionGetForId(uint32_t sessionId) {
31 if (gSessionCurrent != NULL && gSessionCurrent->id == sessionId) {
32 return gSessionCurrent;
33 }
34 return NULL;
35}
36
37bool eicSessionInit(EicSession* ctx) {
38 eicMemSet(ctx, '\0', sizeof(EicSession));
39
40 if (!eicNextId(&gSessionLastIdAssigned)) {
41 eicDebug("Error getting id for object");
42 return false;
43 }
44 ctx->id = gSessionLastIdAssigned;
45
46 do {
47 if (!eicOpsRandom((uint8_t*)&(ctx->authChallenge), sizeof(ctx->authChallenge))) {
48 eicDebug("Failed generating random challenge");
49 return false;
50 }
51 } while (ctx->authChallenge == EIC_KM_AUTH_CHALLENGE_UNSET);
52
53 if (!eicOpsCreateEcKey(ctx->ephemeralPrivateKey, ctx->ephemeralPublicKey)) {
54 eicDebug("Error creating ephemeral key-pair");
55 return false;
56 }
57
58 gSessionCurrent = ctx;
59 eicDebug("Initialized session with id %" PRIu32, ctx->id);
60 return true;
61}
62
63bool eicSessionShutdown(EicSession* ctx) {
64 if (ctx->id == 0) {
65 eicDebug("Trying to shut down session with id 0");
66 return false;
67 }
68 eicDebug("Shut down session with id %" PRIu32, ctx->id);
69 eicMemSet(ctx, '\0', sizeof(EicSession));
70 gSessionCurrent = NULL;
71 return true;
72}
73
74bool eicSessionGetId(EicSession* ctx, uint32_t* outId) {
75 *outId = ctx->id;
76 return true;
77}
78
79bool eicSessionGetAuthChallenge(EicSession* ctx, uint64_t* outAuthChallenge) {
80 *outAuthChallenge = ctx->authChallenge;
81 return true;
82}
83
84bool eicSessionGetEphemeralKeyPair(EicSession* ctx,
85 uint8_t ephemeralPrivateKey[EIC_P256_PRIV_KEY_SIZE]) {
86 eicMemCpy(ephemeralPrivateKey, ctx->ephemeralPrivateKey, EIC_P256_PRIV_KEY_SIZE);
87 return true;
88}
89
90bool eicSessionSetReaderEphemeralPublicKey(
91 EicSession* ctx, const uint8_t readerEphemeralPublicKey[EIC_P256_PUB_KEY_SIZE]) {
92 eicMemCpy(ctx->readerEphemeralPublicKey, readerEphemeralPublicKey, EIC_P256_PUB_KEY_SIZE);
93 return true;
94}
95
96bool eicSessionSetSessionTranscript(EicSession* ctx, const uint8_t* sessionTranscript,
97 size_t sessionTranscriptSize) {
98 // Only accept the SessionTranscript if X and Y from the ephemeral key
99 // we created is somewhere in SessionTranscript...
100 //
101 if (eicMemMem(sessionTranscript, sessionTranscriptSize, ctx->ephemeralPublicKey,
102 EIC_P256_PUB_KEY_SIZE / 2) == NULL) {
103 eicDebug("Error finding X from ephemeralPublicKey in sessionTranscript");
104 return false;
105 }
106 if (eicMemMem(sessionTranscript, sessionTranscriptSize,
107 ctx->ephemeralPublicKey + EIC_P256_PUB_KEY_SIZE / 2,
108 EIC_P256_PUB_KEY_SIZE / 2) == NULL) {
109 eicDebug("Error finding Y from ephemeralPublicKey in sessionTranscript");
110 return false;
111 }
112
113 // To save space we only store the SHA-256 of SessionTranscript
114 //
115 EicSha256Ctx shaCtx;
116 eicOpsSha256Init(&shaCtx);
117 eicOpsSha256Update(&shaCtx, sessionTranscript, sessionTranscriptSize);
118 eicOpsSha256Final(&shaCtx, ctx->sessionTranscriptSha256);
119 return true;
120}