1 /*
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 //
24 static uint32_t gSessionLastIdAssigned = 0;
25
26 // The current session object or NULL if never initialized or if it has been shut down.
27 //
28 static EicSession* gSessionCurrent = NULL;
29
eicSessionGetForId(uint32_t sessionId)30 EicSession* eicSessionGetForId(uint32_t sessionId) {
31 if (gSessionCurrent != NULL && gSessionCurrent->id == sessionId) {
32 return gSessionCurrent;
33 }
34 return NULL;
35 }
36
eicSessionInit(EicSession * ctx)37 bool 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
eicSessionShutdown(EicSession * ctx)63 bool 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
eicSessionGetId(EicSession * ctx,uint32_t * outId)74 bool eicSessionGetId(EicSession* ctx, uint32_t* outId) {
75 *outId = ctx->id;
76 return true;
77 }
78
eicSessionGetAuthChallenge(EicSession * ctx,uint64_t * outAuthChallenge)79 bool eicSessionGetAuthChallenge(EicSession* ctx, uint64_t* outAuthChallenge) {
80 *outAuthChallenge = ctx->authChallenge;
81 return true;
82 }
83
eicSessionGetEphemeralKeyPair(EicSession * ctx,uint8_t ephemeralPrivateKey[EIC_P256_PRIV_KEY_SIZE])84 bool eicSessionGetEphemeralKeyPair(EicSession* ctx,
85 uint8_t ephemeralPrivateKey[EIC_P256_PRIV_KEY_SIZE]) {
86 eicMemCpy(ephemeralPrivateKey, ctx->ephemeralPrivateKey, EIC_P256_PRIV_KEY_SIZE);
87 ctx->getEphemeralKeyPairCalled = true;
88 return true;
89 }
90
eicSessionSetReaderEphemeralPublicKey(EicSession * ctx,const uint8_t readerEphemeralPublicKey[EIC_P256_PUB_KEY_SIZE])91 bool eicSessionSetReaderEphemeralPublicKey(
92 EicSession* ctx, const uint8_t readerEphemeralPublicKey[EIC_P256_PUB_KEY_SIZE]) {
93 eicMemCpy(ctx->readerEphemeralPublicKey, readerEphemeralPublicKey, EIC_P256_PUB_KEY_SIZE);
94 ctx->readerEphemeralPublicKeySize = EIC_P256_PUB_KEY_SIZE;
95 return true;
96 }
97
eicSessionSetSessionTranscript(EicSession * ctx,const uint8_t * sessionTranscript,size_t sessionTranscriptSize)98 bool eicSessionSetSessionTranscript(EicSession* ctx, const uint8_t* sessionTranscript,
99 size_t sessionTranscriptSize) {
100 // If mdoc session encryption is in use, only accept the
101 // SessionTranscript if X and Y from the ephemeral key we created
102 // is somewhere in SessionTranscript...
103 //
104 if (ctx->getEphemeralKeyPairCalled) {
105 if (eicMemMem(sessionTranscript, sessionTranscriptSize, ctx->ephemeralPublicKey,
106 EIC_P256_PUB_KEY_SIZE / 2) == NULL) {
107 eicDebug("Error finding X from ephemeralPublicKey in sessionTranscript");
108 return false;
109 }
110 if (eicMemMem(sessionTranscript, sessionTranscriptSize,
111 ctx->ephemeralPublicKey + EIC_P256_PUB_KEY_SIZE / 2,
112 EIC_P256_PUB_KEY_SIZE / 2) == NULL) {
113 eicDebug("Error finding Y from ephemeralPublicKey in sessionTranscript");
114 return false;
115 }
116 }
117
118 // To save space we only store the SHA-256 of SessionTranscript
119 //
120 EicSha256Ctx shaCtx;
121 eicOpsSha256Init(&shaCtx);
122 eicOpsSha256Update(&shaCtx, sessionTranscript, sessionTranscriptSize);
123 eicOpsSha256Final(&shaCtx, ctx->sessionTranscriptSha256);
124 return true;
125 }
126