blob: 827d7af243394f12cf51c0851d825b1b233c349b [file] [log] [blame]
Andreas Hubered3e3e02012-03-26 11:13:27 -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//#define LOG_NDEBUG 0
18#define LOG_TAG "ICrypto"
19#include <utils/Log.h>
20
21#include <binder/Parcel.h>
22#include <media/ICrypto.h>
23#include <media/stagefright/foundation/ADebug.h>
24
25namespace android {
26
27enum {
28 INITIALIZE = IBinder::FIRST_CALL_TRANSACTION,
29 TERMINATE,
30 SET_ENTITLEMENT_KEY,
31 SET_ECM,
32 DECRYPT_VIDEO,
33 DECRYPT_AUDIO,
34};
35
36struct BpCrypto : public BpInterface<ICrypto> {
37 BpCrypto(const sp<IBinder> &impl)
38 : BpInterface<ICrypto>(impl) {
39 }
40
41 virtual status_t initialize() {
42 Parcel data, reply;
43 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
44 remote()->transact(INITIALIZE, data, &reply);
45
46 return reply.readInt32();
47 }
48
49 virtual status_t terminate() {
50 Parcel data, reply;
51 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
52 remote()->transact(TERMINATE, data, &reply);
53
54 return reply.readInt32();
55 }
56
57 virtual status_t setEntitlementKey(
58 const void *key, size_t keyLength) {
59 Parcel data, reply;
60 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
61 data.writeInt32(keyLength);
62 data.write(key, keyLength);
63 remote()->transact(SET_ENTITLEMENT_KEY, data, &reply);
64
65 return reply.readInt32();
66 }
67
68 virtual status_t setEntitlementControlMessage(
69 const void *msg, size_t msgLength) {
70 Parcel data, reply;
71 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
72 data.writeInt32(msgLength);
73 data.write(msg, msgLength);
74 remote()->transact(SET_ECM, data, &reply);
75
76 return reply.readInt32();
77 }
78
79 virtual ssize_t decryptVideo(
80 const void *iv, size_t ivLength,
81 const void *srcData, size_t srcDataSize,
82 void *dstData, size_t dstDataOffset) {
83 Parcel data, reply;
84 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
85 if (iv == NULL) {
86 if (ivLength > 0) {
87 return -EINVAL;
88 }
89
90 data.writeInt32(-1);
91 } else {
92 data.writeInt32(ivLength);
93 data.write(iv, ivLength);
94 }
95
96 data.writeInt32(srcDataSize);
97 data.write(srcData, srcDataSize);
98
99 data.writeIntPtr((intptr_t)dstData);
100 data.writeInt32(dstDataOffset);
101
102 remote()->transact(DECRYPT_VIDEO, data, &reply);
103
104 return reply.readInt32();
105 }
106
107 virtual ssize_t decryptAudio(
108 const void *iv, size_t ivLength,
109 const void *srcData, size_t srcDataSize,
110 void *dstData, size_t dstDataSize) {
111 Parcel data, reply;
112 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
113 if (iv == NULL) {
114 if (ivLength > 0) {
115 return -EINVAL;
116 }
117
118 data.writeInt32(-1);
119 } else {
120 data.writeInt32(ivLength);
121 data.write(iv, ivLength);
122 }
123
124 data.writeInt32(srcDataSize);
125 data.write(srcData, srcDataSize);
126 data.writeInt32(dstDataSize);
127
128 remote()->transact(DECRYPT_AUDIO, data, &reply);
129
130 ssize_t res = reply.readInt32();
131
132 if (res <= 0) {
133 return res;
134 }
135
136 reply.read(dstData, res);
137
138 return res;
139 }
140
141private:
142 DISALLOW_EVIL_CONSTRUCTORS(BpCrypto);
143};
144
145IMPLEMENT_META_INTERFACE(Crypto, "android.hardware.ICrypto");
146
147////////////////////////////////////////////////////////////////////////////////
148
149status_t BnCrypto::onTransact(
150 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
151 switch (code) {
152 case INITIALIZE:
153 {
154 CHECK_INTERFACE(ICrypto, data, reply);
155 reply->writeInt32(initialize());
156
157 return OK;
158 }
159
160 case TERMINATE:
161 {
162 CHECK_INTERFACE(ICrypto, data, reply);
163 reply->writeInt32(terminate());
164
165 return OK;
166 }
167
168 case SET_ENTITLEMENT_KEY:
169 {
170 CHECK_INTERFACE(ICrypto, data, reply);
171
172 size_t keyLength = data.readInt32();
173 void *key = malloc(keyLength);
174 data.read(key, keyLength);
175
176 reply->writeInt32(setEntitlementKey(key, keyLength));
177
178 free(key);
179 key = NULL;
180
181 return OK;
182 }
183
184 case SET_ECM:
185 {
186 CHECK_INTERFACE(ICrypto, data, reply);
187
188 size_t msgLength = data.readInt32();
189 void *msg = malloc(msgLength);
190 data.read(msg, msgLength);
191
192 reply->writeInt32(setEntitlementControlMessage(msg, msgLength));
193
194 free(msg);
195 msg = NULL;
196
197 return OK;
198 }
199
200 case DECRYPT_VIDEO:
201 {
202 CHECK_INTERFACE(ICrypto, data, reply);
203
204 void *iv = NULL;
205
206 int32_t ivLength = data.readInt32();
207 if (ivLength >= 0) {
208 iv = malloc(ivLength);
209 data.read(iv, ivLength);
210 }
211
212 size_t srcDataSize = data.readInt32();
213 void *srcData = malloc(srcDataSize);
214 data.read(srcData, srcDataSize);
215
216 void *dstData = (void *)data.readIntPtr();
217 size_t dstDataOffset = data.readInt32();
218
219 reply->writeInt32(
220 decryptVideo(
221 iv,
222 ivLength < 0 ? 0 : ivLength,
223 srcData,
224 srcDataSize,
225 dstData,
226 dstDataOffset));
227
228 free(srcData);
229 srcData = NULL;
230
231 if (iv != NULL) {
232 free(iv);
233 iv = NULL;
234 }
235
236 return OK;
237 }
238
239 case DECRYPT_AUDIO:
240 {
241 CHECK_INTERFACE(ICrypto, data, reply);
242
243 void *iv = NULL;
244
245 int32_t ivLength = data.readInt32();
246 if (ivLength >= 0) {
247 iv = malloc(ivLength);
248 data.read(iv, ivLength);
249 }
250
251 size_t srcDataSize = data.readInt32();
252 void *srcData = malloc(srcDataSize);
253 data.read(srcData, srcDataSize);
254
255 size_t dstDataSize = data.readInt32();
256 void *dstData = malloc(dstDataSize);
257
258 ssize_t res =
259 decryptAudio(
260 iv,
261 ivLength < 0 ? 0 : ivLength,
262 srcData,
263 srcDataSize,
264 dstData,
265 dstDataSize);
266
267 reply->writeInt32(res);
268
269 if (res > 0) {
270 reply->write(dstData, res);
271 }
272
273 free(dstData);
274 dstData = NULL;
275
276 free(srcData);
277 srcData = NULL;
278
279 if (iv != NULL) {
280 free(iv);
281 iv = NULL;
282 }
283
284 return OK;
285 }
286
287 default:
288 return BBinder::onTransact(code, data, reply, flags);
289 }
290}
291
292} // namespace android
293