1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 #include "mozilla/Unused.h"
6 #include "SinfParser.h"
7 #include "AtomType.h"
8 #include "Box.h"
9 #include "ByteStream.h"
10 
11 namespace mozilla {
12 
Sinf(Box & aBox)13 Sinf::Sinf(Box& aBox) : mDefaultIVSize(0), mDefaultEncryptionType() {
14   SinfParser parser(aBox);
15   if (parser.GetSinf().IsValid()) {
16     *this = parser.GetSinf();
17   }
18 }
19 
SinfParser(Box & aBox)20 SinfParser::SinfParser(Box& aBox) {
21   for (Box box = aBox.FirstChild(); box.IsAvailable(); box = box.Next()) {
22     if (box.IsType("schm")) {
23       mozilla::Unused << ParseSchm(box);
24     } else if (box.IsType("schi")) {
25       mozilla::Unused << ParseSchi(box);
26     }
27   }
28 }
29 
ParseSchm(Box & aBox)30 Result<Ok, nsresult> SinfParser::ParseSchm(Box& aBox) {
31   BoxReader reader(aBox);
32 
33   if (reader->Remaining() < 8) {
34     return Err(NS_ERROR_FAILURE);
35   }
36 
37   MOZ_TRY(reader->ReadU32());  // flags -- ignore
38   MOZ_TRY_VAR(mSinf.mDefaultEncryptionType, reader->ReadU32());
39   return Ok();
40 }
41 
ParseSchi(Box & aBox)42 Result<Ok, nsresult> SinfParser::ParseSchi(Box& aBox) {
43   for (Box box = aBox.FirstChild(); box.IsAvailable(); box = box.Next()) {
44     if (box.IsType("tenc") && ParseTenc(box).isErr()) {
45       return Err(NS_ERROR_FAILURE);
46     }
47   }
48   return Ok();
49 }
50 
ParseTenc(Box & aBox)51 Result<Ok, nsresult> SinfParser::ParseTenc(Box& aBox) {
52   BoxReader reader(aBox);
53 
54   if (reader->Remaining() < 24) {
55     return Err(NS_ERROR_FAILURE);
56   }
57 
58   uint32_t flags;
59   MOZ_TRY_VAR(flags, reader->ReadU32());
60   uint8_t version = flags >> 24;
61 
62   // Skip reserved byte
63   MOZ_TRY(reader->ReadU8());
64   if (version >= 1) {
65     uint8_t pattern;
66     MOZ_TRY_VAR(pattern, reader->ReadU8());
67     mSinf.mDefaultCryptByteBlock = pattern >> 4;
68     mSinf.mDefaultSkipByteBlock = pattern & 0x0f;
69   } else {
70     // Reserved if version is less than 1
71     MOZ_TRY(reader->ReadU8());
72     mSinf.mDefaultCryptByteBlock = 0;
73     mSinf.mDefaultSkipByteBlock = 0;
74   }
75 
76   uint8_t isEncrypted;
77   MOZ_TRY_VAR(isEncrypted, reader->ReadU8());
78   MOZ_TRY_VAR(mSinf.mDefaultIVSize, reader->ReadU8());
79   memcpy(mSinf.mDefaultKeyID, reader->Read(16), 16);
80 
81   if (isEncrypted && mSinf.mDefaultIVSize == 0) {
82     uint8_t defaultConstantIVSize;
83     MOZ_TRY_VAR(defaultConstantIVSize, reader->ReadU8());
84     if (!mSinf.mDefaultConstantIV.SetLength(defaultConstantIVSize,
85                                             mozilla::fallible)) {
86       return Err(NS_ERROR_FAILURE);
87     }
88     for (uint8_t i = 0; i < defaultConstantIVSize; i++) {
89       MOZ_TRY_VAR(mSinf.mDefaultConstantIV.ElementAt(i), reader->ReadU8());
90     }
91   }
92   return Ok();
93 }
94 
95 }  // namespace mozilla
96