blob: d0f173b572c8e776d571ec25dc013d4bc436d48b [file] [log] [blame]
Victor Hsieh38c55032018-09-26 12:44:53 -07001/*
2 * Copyright (C) 2018 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_TAG "VerityUtils"
18
19#include <nativehelper/JNIHelp.h>
20#include "jni.h"
21#include <utils/Log.h>
22
23#include <string.h>
24
25// TODO(112037636): Always include once fsverity.h is upstreamed and backported.
26#define HAS_FSVERITY 0
27
28#if HAS_FSVERITY
29#include <linux/fsverity.h>
30#endif
31
32namespace android {
33
34namespace {
35
36class JavaByteArrayHolder {
37 public:
38 static JavaByteArrayHolder* newArray(JNIEnv* env, jsize size) {
39 return new JavaByteArrayHolder(env, size);
40 }
41
42 jbyte* getRaw() {
43 return mElements;
44 }
45
46 jbyteArray release() {
47 mEnv->ReleaseByteArrayElements(mBytes, mElements, 0);
48 mElements = nullptr;
49 return mBytes;
50 }
51
52 private:
53 JavaByteArrayHolder(JNIEnv* env, jsize size) {
54 mEnv = env;
55 mBytes = mEnv->NewByteArray(size);
56 mElements = mEnv->GetByteArrayElements(mBytes, nullptr);
57 memset(mElements, 0, size);
58 }
59
60 virtual ~JavaByteArrayHolder() {
61 LOG_ALWAYS_FATAL_IF(mElements == nullptr, "Elements are not released");
62 }
63
64 JNIEnv* mEnv;
65 jbyteArray mBytes;
66 jbyte* mElements;
67};
68
69jbyteArray constructFsverityDescriptor(JNIEnv* env, jobject /* clazz */, jlong fileSize) {
70#if HAS_FSVERITY
71 auto raii = JavaByteArrayHolder::newArray(env, sizeof(fsverity_descriptor));
72 fsverity_descriptor* desc = reinterpret_cast<fsverity_descriptor*>(raii->getRaw());
73
74 memcpy(desc->magic, FS_VERITY_MAGIC, sizeof(desc->magic));
75 desc->major_version = 1;
76 desc->minor_version = 0;
77 desc->log_data_blocksize = 12;
78 desc->log_tree_blocksize = 12;
79 desc->data_algorithm = FS_VERITY_ALG_SHA256;
80 desc->tree_algorithm = FS_VERITY_ALG_SHA256;
81 desc->flags = 0;
82 desc->orig_file_size = fileSize;
83 desc->auth_ext_count = 1;
84
85 return raii->release();
86#else
87 LOG_ALWAYS_FATAL("fs-verity is used while not enabled");
88 return 0;
89#endif // HAS_FSVERITY
90}
91
92jbyteArray constructFsverityExtension(JNIEnv* env, jobject /* clazz */, jshort extensionId,
93 jint extensionDataSize) {
94#if HAS_FSVERITY
95 auto raii = JavaByteArrayHolder::newArray(env, sizeof(fsverity_extension));
96 fsverity_extension* ext = reinterpret_cast<fsverity_extension*>(raii->getRaw());
97
98 ext->length = sizeof(fsverity_extension) + extensionDataSize;
99 ext->type = extensionId;
100
101 return raii->release();
102#else
103 LOG_ALWAYS_FATAL("fs-verity is used while not enabled");
104 return 0;
105#endif // HAS_FSVERITY
106}
107
108jbyteArray constructFsverityFooter(JNIEnv* env, jobject /* clazz */,
109 jint offsetToDescriptorHead) {
110#if HAS_FSVERITY
111 auto raii = JavaByteArrayHolder::newArray(env, sizeof(fsverity_footer));
112 fsverity_footer* footer = reinterpret_cast<fsverity_footer*>(raii->getRaw());
113
114 footer->desc_reverse_offset = offsetToDescriptorHead + sizeof(fsverity_footer);
115 memcpy(footer->magic, FS_VERITY_MAGIC, sizeof(footer->magic));
116
117 return raii->release();
118#else
119 LOG_ALWAYS_FATAL("fs-verity is used while not enabled");
120 return 0;
121#endif // HAS_FSVERITY
122}
123
124const JNINativeMethod sMethods[] = {
125 { "constructFsverityDescriptorNative", "(J)[B", (void *)constructFsverityDescriptor },
126 { "constructFsverityExtensionNative", "(SI)[B", (void *)constructFsverityExtension },
127 { "constructFsverityFooterNative", "(I)[B", (void *)constructFsverityFooter },
128};
129
130} // namespace
131
132int register_android_server_security_VerityUtils(JNIEnv* env) {
133 return jniRegisterNativeMethods(env,
134 "com/android/server/security/VerityUtils", sMethods, NELEM(sMethods));
135}
136
137} // namespace android