1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ppapi/proxy/platform_verification_private_resource.h"
6
7#include "base/bind.h"
8#include "ppapi/c/pp_errors.h"
9#include "ppapi/proxy/dispatch_reply_message.h"
10#include "ppapi/proxy/ppapi_messages.h"
11#include "ppapi/shared_impl/ppapi_globals.h"
12#include "ppapi/shared_impl/tracked_callback.h"
13#include "ppapi/shared_impl/var.h"
14#include "ppapi/shared_impl/var_tracker.h"
15
16namespace ppapi {
17namespace proxy {
18
19PlatformVerificationPrivateResource::PlatformVerificationPrivateResource(
20    Connection connection,
21    PP_Instance instance)
22    : PluginResource(connection, instance) {
23  SendCreate(BROWSER, PpapiHostMsg_PlatformVerification_Create());
24}
25
26PlatformVerificationPrivateResource::~PlatformVerificationPrivateResource() {}
27
28thunk::PPB_PlatformVerification_API*
29PlatformVerificationPrivateResource::AsPPB_PlatformVerification_API() {
30  return this;
31}
32
33int32_t PlatformVerificationPrivateResource::ChallengePlatform(
34    const PP_Var& service_id,
35    const PP_Var& challenge,
36    PP_Var* signed_data,
37    PP_Var* signed_data_signature,
38    PP_Var* platform_key_certificate,
39    const scoped_refptr<TrackedCallback>& callback) {
40  // Prevent null types for obvious reasons, but also ref-counted types to avoid
41  // leaks on challenge failures (since they're only written to on success).
42  if (!signed_data || !signed_data_signature || !platform_key_certificate ||
43      VarTracker::IsVarTypeRefcounted(signed_data->type) ||
44      VarTracker::IsVarTypeRefcounted(signed_data_signature->type) ||
45      VarTracker::IsVarTypeRefcounted(platform_key_certificate->type)) {
46    return PP_ERROR_BADARGUMENT;
47  }
48
49  StringVar* service_id_str = StringVar::FromPPVar(service_id);
50  if (!service_id_str)
51    return PP_ERROR_BADARGUMENT;
52
53  scoped_refptr<ArrayBufferVar> challenge_buffer =
54      ArrayBufferVar::FromPPVar(challenge);
55  if (!challenge_buffer.get())
56    return PP_ERROR_BADARGUMENT;
57
58  uint8_t* challenge_data = static_cast<uint8_t*>(challenge_buffer->Map());
59  uint32 challenge_length = challenge_buffer->ByteLength();
60  std::vector<uint8_t> challenge_vector(challenge_data,
61                                        challenge_data + challenge_length);
62  challenge_buffer->Unmap();
63
64  PpapiHostMsg_PlatformVerification_ChallengePlatform challenge_message(
65      service_id_str->value(), challenge_vector);
66
67  ChallengePlatformParams output_params = {
68      signed_data, signed_data_signature, platform_key_certificate, callback };
69
70  Call<PpapiHostMsg_PlatformVerification_ChallengePlatformReply>(
71      BROWSER, challenge_message, base::Bind(
72          &PlatformVerificationPrivateResource::OnChallengePlatformReply,
73          base::Unretained(this), output_params));
74  return PP_OK_COMPLETIONPENDING;
75}
76
77void PlatformVerificationPrivateResource::OnChallengePlatformReply(
78    ChallengePlatformParams output_params,
79    const ResourceMessageReplyParams& params,
80    const std::vector<uint8_t>& raw_signed_data,
81    const std::vector<uint8_t>& raw_signed_data_signature,
82    const std::string& raw_platform_key_certificate) {
83  if (!TrackedCallback::IsPending(output_params.callback) ||
84      TrackedCallback::IsScheduledToRun(output_params.callback)) {
85    return;
86  }
87
88  if (params.result() == PP_OK) {
89    *(output_params.signed_data) =
90        (PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferVar(
91            raw_signed_data.size(), &raw_signed_data.front()))->GetPPVar();
92    *(output_params.signed_data_signature) =
93        (PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferVar(
94            raw_signed_data_signature.size(),
95            &raw_signed_data_signature.front()))->GetPPVar();
96    *(output_params.platform_key_certificate) =
97        (new StringVar(raw_platform_key_certificate))->GetPPVar();
98  }
99  output_params.callback->Run(params.result());
100}
101
102}  // namespace proxy
103}  // namespace ppapi
104