CryptoPlugin.cpp revision 9472e5f3ab44f04c92e44ad0f3e94c0ee508ec11
11fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce/*
21fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce * Copyright (C) 2014 The Android Open Source Project
31fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce *
41fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce * Licensed under the Apache License, Version 2.0 (the "License");
51fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce * you may not use this file except in compliance with the License.
61fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce * You may obtain a copy of the License at
71fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce *
81fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce *      http://www.apache.org/licenses/LICENSE-2.0
91fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce *
101fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce * Unless required by applicable law or agreed to in writing, software
111fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce * distributed under the License is distributed on an "AS IS" BASIS,
121fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce * See the License for the specific language governing permissions and
141fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce * limitations under the License.
151fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce */
161fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce
171fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce//#define LOG_NDEBUG 0
181fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce#define LOG_TAG "ClearKeyCryptoPlugin"
191fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce#include <utils/Log.h>
201fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce
211fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce#include <media/stagefright/MediaErrors.h>
221fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce
231fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce#include "CryptoPlugin.h"
249472e5f3ab44f04c92e44ad0f3e94c0ee508ec11Jeff Tinker#include "SessionLibrary.h"
251fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce
261fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Brucenamespace clearkeydrm {
271fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce
281fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruceusing android::Vector;
291fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruceusing android::AString;
301fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruceusing android::status_t;
311fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce
321fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce// Returns negative values for error code and positive values for the size of
331fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce// decrypted data.  In theory, the output size can be larger than the input
341fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce// size, but in practice this will never happen for AES-CTR.
351fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Brucessize_t CryptoPlugin::decrypt(bool secure, const KeyId keyId, const Iv iv,
361fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce                              Mode mode, const void* srcPtr,
371fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce                              const SubSample* subSamples, size_t numSubSamples,
381fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce                              void* dstPtr, AString* errorDetailMsg) {
391fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce    if (secure) {
401fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce        errorDetailMsg->setTo("Secure decryption is not supported with "
411fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce                              "ClearKey.");
421fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce        return android::ERROR_DRM_CANNOT_HANDLE;
431fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce    }
441fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce
451fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce    if (mode == kMode_Unencrypted) {
461fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce        size_t offset = 0;
471fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce        for (size_t i = 0; i < numSubSamples; ++i) {
481fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce            const SubSample& subSample = subSamples[i];
491fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce
501fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce            if (subSample.mNumBytesOfEncryptedData != 0) {
511fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce                errorDetailMsg->setTo(
521fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce                        "Encrypted subsamples found in allegedly unencrypted "
531fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce                        "data.");
541fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce                return android::ERROR_DRM_DECRYPT;
551fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce            }
561fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce
571fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce            if (subSample.mNumBytesOfClearData != 0) {
581fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce                memcpy(reinterpret_cast<uint8_t*>(dstPtr) + offset,
591fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce                       reinterpret_cast<const uint8_t*>(srcPtr) + offset,
601fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce                       subSample.mNumBytesOfClearData);
611fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce                offset += subSample.mNumBytesOfClearData;
621fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce            }
631fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce        }
641fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce        return static_cast<ssize_t>(offset);
651fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce    } else if (mode == kMode_AES_CTR) {
661fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce        size_t bytesDecrypted;
671fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce        status_t res = mSession->decrypt(keyId, iv, srcPtr, dstPtr, subSamples,
681fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce                                         numSubSamples, &bytesDecrypted);
691fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce        if (res == android::OK) {
701fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce            return static_cast<ssize_t>(bytesDecrypted);
711fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce        } else {
721fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce            errorDetailMsg->setTo("Decryption Error");
731fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce            return static_cast<ssize_t>(res);
741fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce        }
751fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce    } else {
761fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce        errorDetailMsg->setTo(
771fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce                "Selected encryption mode is not supported by the ClearKey DRM "
781fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce                "Plugin.");
791fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce        return android::ERROR_DRM_CANNOT_HANDLE;
801fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce    }
811fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce}
821fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce
839472e5f3ab44f04c92e44ad0f3e94c0ee508ec11Jeff Tinkerandroid::status_t CryptoPlugin::setMediaDrmSession(
849472e5f3ab44f04c92e44ad0f3e94c0ee508ec11Jeff Tinker        const android::Vector<uint8_t>& sessionId) {
859472e5f3ab44f04c92e44ad0f3e94c0ee508ec11Jeff Tinker    if (!sessionId.size()) {
869472e5f3ab44f04c92e44ad0f3e94c0ee508ec11Jeff Tinker        mSession.clear();
879472e5f3ab44f04c92e44ad0f3e94c0ee508ec11Jeff Tinker    } else {
889472e5f3ab44f04c92e44ad0f3e94c0ee508ec11Jeff Tinker        mSession = SessionLibrary::get()->findSession(sessionId);
899472e5f3ab44f04c92e44ad0f3e94c0ee508ec11Jeff Tinker        if (!mSession.get()) {
909472e5f3ab44f04c92e44ad0f3e94c0ee508ec11Jeff Tinker            return android::ERROR_DRM_SESSION_NOT_OPENED;
919472e5f3ab44f04c92e44ad0f3e94c0ee508ec11Jeff Tinker        }
929472e5f3ab44f04c92e44ad0f3e94c0ee508ec11Jeff Tinker    }
939472e5f3ab44f04c92e44ad0f3e94c0ee508ec11Jeff Tinker    return android::OK;
949472e5f3ab44f04c92e44ad0f3e94c0ee508ec11Jeff Tinker}
959472e5f3ab44f04c92e44ad0f3e94c0ee508ec11Jeff Tinker
969472e5f3ab44f04c92e44ad0f3e94c0ee508ec11Jeff Tinker
971fe11a5d1b7932a8a4a4e6e8cf1aedd21fcdb3aaJohn "Juce" Bruce}  // namespace clearkeydrm
98