blob: db9eb680c4f2503396f71301a8511328f3098d30 [file] [log] [blame]
Kenny Root51878182012-03-13 12:53:19 -07001/*
2 * Copyright (C) 2012 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 <keystore.h>
18#include <keystore_client.h>
19
20#include <cutils/sockets.h>
21
22#define LOG_TAG "keystore_client"
23#include <cutils/log.h>
24
25ResponseCode keystore_cmd(command_code_t cmd, Keystore_Reply* reply, int numArgs, ...) {
26 int sock;
27
28 sock = socket_local_client("keystore", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
29 if (sock == -1) {
30 return SYSTEM_ERROR;
31 }
32
33 if (TEMP_FAILURE_RETRY(send(sock, &cmd, 1, MSG_NOSIGNAL)) != 1) {
34 close(sock);
35 return SYSTEM_ERROR;
36 }
37
38 va_list vl;
39 va_start(vl, numArgs);
40 for (int i = 0; i < numArgs; i++) {
41 size_t argLen = va_arg(vl, size_t);
42 uint8_t* arg = va_arg(vl, uint8_t*);
43
44 if (argLen > KEYSTORE_MESSAGE_SIZE) {
45 ALOGE("code called us with an argLen out of bounds: %llu", (unsigned long long) argLen);
46 close(sock);
47 return SYSTEM_ERROR;
48 }
49
50 uint8_t bytes[2] = { argLen >> 8, argLen };
51 if (TEMP_FAILURE_RETRY(send(sock, bytes, 2, MSG_NOSIGNAL)) != 2
52 || TEMP_FAILURE_RETRY(send(sock, arg, argLen, MSG_NOSIGNAL))
53 != static_cast<ssize_t>(argLen)) {
54 ALOGW("truncated write to keystore");
55 close(sock);
56 return SYSTEM_ERROR;
57 }
58 }
59 va_end(vl);
60
61 uint8_t code = 0;
62 if (shutdown(sock, SHUT_WR) != 0
63 || TEMP_FAILURE_RETRY(recv(sock, &code, 1, 0)) != 1
64 || code != NO_ERROR) {
65 ALOGW("Error from keystore: %d", code);
66 close(sock);
67 return SYSTEM_ERROR;
68 }
69
70 if (reply != NULL) {
71 reply->setCode(static_cast<ResponseCode>(code));
72
73 uint8_t bytes[2];
74 uint8_t* data = reply->get();
75 if (TEMP_FAILURE_RETRY(recv(sock, &bytes[0], 1, 0)) == 1
76 && TEMP_FAILURE_RETRY(recv(sock, &bytes[1], 1, 0)) == 1) {
77 int offset = 0;
78 int length = bytes[0] << 8 | bytes[1];
79 while (offset < length) {
80 int n = TEMP_FAILURE_RETRY(recv(sock, &data[offset], length - offset, 0));
81 if (n <= 0) {
82 ALOGW("truncated read from keystore for data");
83 code = SYSTEM_ERROR;
84 break;
85 }
86 offset += n;
87 }
88 reply->setLength(length);
89 } else {
90 ALOGW("truncated read from keystore for length");
91 code = SYSTEM_ERROR;
92 }
93 }
94
95 close(sock);
96 return static_cast<ResponseCode>(code);
97}
98
99Keystore_Reply::Keystore_Reply()
100 : mCode(SYSTEM_ERROR)
101 , mLength(-1) {
102 mData = new uint8_t[KEYSTORE_MESSAGE_SIZE];
103}
104
105Keystore_Reply::~Keystore_Reply() {
106 delete[] mData;
107}
108
109uint8_t* Keystore_Reply::get() {
110 return mData;
111}
112
113void Keystore_Reply::setLength(size_t length) {
114 mLength = length;
115}
116
117size_t Keystore_Reply::length() const {
118 return mLength;
119}
120
121void Keystore_Reply::setCode(ResponseCode code) {
122 mCode = code;
123}
124
125ResponseCode Keystore_Reply::code() const {
126 return mCode;
127}
128
129uint8_t* Keystore_Reply::release() {
130 uint8_t* data = mData;
131 mData = NULL;
132 return data;
133}