Home | History | Annotate | Download | only in default
      1 /*
      2  * Copyright (C) 2014 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 "ClearKeyCryptoPlugin"
     19 #include <utils/Log.h>
     20 
     21 #include <media/stagefright/MediaErrors.h>
     22 
     23 #include "CryptoPlugin.h"
     24 #include "SessionLibrary.h"
     25 
     26 namespace clearkeydrm {
     27 
     28 using android::Vector;
     29 using android::AString;
     30 using android::status_t;
     31 
     32 // Returns negative values for error code and positive values for the size of
     33 // decrypted data.  In theory, the output size can be larger than the input
     34 // size, but in practice this will never happen for AES-CTR.
     35 ssize_t CryptoPlugin::decrypt(bool secure, const KeyId keyId, const Iv iv,
     36                               Mode mode, const Pattern &/* pattern */, const void* srcPtr,
     37                               const SubSample* subSamples, size_t numSubSamples,
     38                               void* dstPtr, AString* errorDetailMsg) {
     39     if (secure) {
     40         errorDetailMsg->setTo("Secure decryption is not supported with "
     41                               "ClearKey.");
     42         return android::ERROR_DRM_CANNOT_HANDLE;
     43     }
     44 
     45     if (mode == kMode_Unencrypted) {
     46         size_t offset = 0;
     47         for (size_t i = 0; i < numSubSamples; ++i) {
     48             const SubSample& subSample = subSamples[i];
     49 
     50             if (subSample.mNumBytesOfEncryptedData != 0) {
     51                 errorDetailMsg->setTo(
     52                         "Encrypted subsamples found in allegedly unencrypted "
     53                         "data.");
     54                 return android::ERROR_DRM_DECRYPT;
     55             }
     56 
     57             if (subSample.mNumBytesOfClearData != 0) {
     58                 memcpy(reinterpret_cast<uint8_t*>(dstPtr) + offset,
     59                        reinterpret_cast<const uint8_t*>(srcPtr) + offset,
     60                        subSample.mNumBytesOfClearData);
     61                 offset += subSample.mNumBytesOfClearData;
     62             }
     63         }
     64         return static_cast<ssize_t>(offset);
     65     } else if (mode == kMode_AES_CTR) {
     66         size_t bytesDecrypted;
     67         status_t res = mSession->decrypt(keyId, iv, srcPtr, dstPtr, subSamples,
     68                                          numSubSamples, &bytesDecrypted);
     69         if (res == android::OK) {
     70             return static_cast<ssize_t>(bytesDecrypted);
     71         } else {
     72             errorDetailMsg->setTo("Decryption Error");
     73             return static_cast<ssize_t>(res);
     74         }
     75     } else {
     76         errorDetailMsg->setTo(
     77                 "Selected encryption mode is not supported by the ClearKey DRM "
     78                 "Plugin.");
     79         return android::ERROR_DRM_CANNOT_HANDLE;
     80     }
     81 }
     82 
     83 android::status_t CryptoPlugin::setMediaDrmSession(
     84         const android::Vector<uint8_t>& sessionId) {
     85     if (!sessionId.size()) {
     86         mSession.clear();
     87     } else {
     88         mSession = SessionLibrary::get()->findSession(sessionId);
     89         if (!mSession.get()) {
     90             return android::ERROR_DRM_SESSION_NOT_OPENED;
     91         }
     92     }
     93     return android::OK;
     94 }
     95 
     96 
     97 }  // namespace clearkeydrm
     98