1"use strict"; 2Object.defineProperty(exports, "__esModule", { value: true }); 3exports.assertBundleLatest = exports.assertBundleV02 = exports.isBundleV01 = exports.assertBundleV01 = exports.assertBundle = void 0; 4/* 5Copyright 2023 The Sigstore Authors. 6 7Licensed under the Apache License, Version 2.0 (the "License"); 8you may not use this file except in compliance with the License. 9You may obtain a copy of the License at 10 11 http://www.apache.org/licenses/LICENSE-2.0 12 13Unless required by applicable law or agreed to in writing, software 14distributed under the License is distributed on an "AS IS" BASIS, 15WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16See the License for the specific language governing permissions and 17limitations under the License. 18*/ 19const error_1 = require("./error"); 20// Performs basic validation of a Sigstore bundle to ensure that all required 21// fields are populated. This is not a complete validation of the bundle, but 22// rather a check that the bundle is in a valid state to be processed by the 23// rest of the code. 24function assertBundle(b) { 25 const invalidValues = validateBundleBase(b); 26 if (invalidValues.length > 0) { 27 throw new error_1.ValidationError('invalid bundle', invalidValues); 28 } 29} 30exports.assertBundle = assertBundle; 31// Asserts that the given bundle conforms to the v0.1 bundle format. 32function assertBundleV01(b) { 33 const invalidValues = []; 34 invalidValues.push(...validateBundleBase(b)); 35 invalidValues.push(...validateInclusionPromise(b)); 36 if (invalidValues.length > 0) { 37 throw new error_1.ValidationError('invalid v0.1 bundle', invalidValues); 38 } 39} 40exports.assertBundleV01 = assertBundleV01; 41// Type guard to determine if Bundle is a v0.1 bundle. 42function isBundleV01(b) { 43 try { 44 assertBundleV01(b); 45 return true; 46 } 47 catch (e) { 48 return false; 49 } 50} 51exports.isBundleV01 = isBundleV01; 52// Asserts that the given bundle conforms to the v0.2 bundle format. 53function assertBundleV02(b) { 54 const invalidValues = []; 55 invalidValues.push(...validateBundleBase(b)); 56 invalidValues.push(...validateInclusionProof(b)); 57 if (invalidValues.length > 0) { 58 throw new error_1.ValidationError('invalid v0.2 bundle', invalidValues); 59 } 60} 61exports.assertBundleV02 = assertBundleV02; 62// Asserts that the given bundle conforms to the newest (0.3) bundle format. 63function assertBundleLatest(b) { 64 const invalidValues = []; 65 invalidValues.push(...validateBundleBase(b)); 66 invalidValues.push(...validateInclusionProof(b)); 67 invalidValues.push(...validateNoCertificateChain(b)); 68 if (invalidValues.length > 0) { 69 throw new error_1.ValidationError('invalid bundle', invalidValues); 70 } 71} 72exports.assertBundleLatest = assertBundleLatest; 73function validateBundleBase(b) { 74 const invalidValues = []; 75 // Media type validation 76 if (b.mediaType === undefined || 77 !b.mediaType.startsWith('application/vnd.dev.sigstore.bundle+json;version=')) { 78 invalidValues.push('mediaType'); 79 } 80 // Content-related validation 81 if (b.content === undefined) { 82 invalidValues.push('content'); 83 } 84 else { 85 switch (b.content.$case) { 86 case 'messageSignature': 87 if (b.content.messageSignature.messageDigest === undefined) { 88 invalidValues.push('content.messageSignature.messageDigest'); 89 } 90 else { 91 if (b.content.messageSignature.messageDigest.digest.length === 0) { 92 invalidValues.push('content.messageSignature.messageDigest.digest'); 93 } 94 } 95 if (b.content.messageSignature.signature.length === 0) { 96 invalidValues.push('content.messageSignature.signature'); 97 } 98 break; 99 case 'dsseEnvelope': 100 if (b.content.dsseEnvelope.payload.length === 0) { 101 invalidValues.push('content.dsseEnvelope.payload'); 102 } 103 if (b.content.dsseEnvelope.signatures.length !== 1) { 104 invalidValues.push('content.dsseEnvelope.signatures'); 105 } 106 else { 107 if (b.content.dsseEnvelope.signatures[0].sig.length === 0) { 108 invalidValues.push('content.dsseEnvelope.signatures[0].sig'); 109 } 110 } 111 break; 112 } 113 } 114 // Verification material-related validation 115 if (b.verificationMaterial === undefined) { 116 invalidValues.push('verificationMaterial'); 117 } 118 else { 119 if (b.verificationMaterial.content === undefined) { 120 invalidValues.push('verificationMaterial.content'); 121 } 122 else { 123 switch (b.verificationMaterial.content.$case) { 124 case 'x509CertificateChain': 125 if (b.verificationMaterial.content.x509CertificateChain.certificates 126 .length === 0) { 127 invalidValues.push('verificationMaterial.content.x509CertificateChain.certificates'); 128 } 129 b.verificationMaterial.content.x509CertificateChain.certificates.forEach((cert, i) => { 130 if (cert.rawBytes.length === 0) { 131 invalidValues.push(`verificationMaterial.content.x509CertificateChain.certificates[${i}].rawBytes`); 132 } 133 }); 134 break; 135 case 'certificate': 136 if (b.verificationMaterial.content.certificate.rawBytes.length === 0) { 137 invalidValues.push('verificationMaterial.content.certificate.rawBytes'); 138 } 139 break; 140 } 141 } 142 if (b.verificationMaterial.tlogEntries === undefined) { 143 invalidValues.push('verificationMaterial.tlogEntries'); 144 } 145 else { 146 if (b.verificationMaterial.tlogEntries.length > 0) { 147 b.verificationMaterial.tlogEntries.forEach((entry, i) => { 148 if (entry.logId === undefined) { 149 invalidValues.push(`verificationMaterial.tlogEntries[${i}].logId`); 150 } 151 if (entry.kindVersion === undefined) { 152 invalidValues.push(`verificationMaterial.tlogEntries[${i}].kindVersion`); 153 } 154 }); 155 } 156 } 157 } 158 return invalidValues; 159} 160// Necessary for V01 bundles 161function validateInclusionPromise(b) { 162 const invalidValues = []; 163 if (b.verificationMaterial && 164 b.verificationMaterial.tlogEntries?.length > 0) { 165 b.verificationMaterial.tlogEntries.forEach((entry, i) => { 166 if (entry.inclusionPromise === undefined) { 167 invalidValues.push(`verificationMaterial.tlogEntries[${i}].inclusionPromise`); 168 } 169 }); 170 } 171 return invalidValues; 172} 173// Necessary for V02 and later bundles 174function validateInclusionProof(b) { 175 const invalidValues = []; 176 if (b.verificationMaterial && 177 b.verificationMaterial.tlogEntries?.length > 0) { 178 b.verificationMaterial.tlogEntries.forEach((entry, i) => { 179 if (entry.inclusionProof === undefined) { 180 invalidValues.push(`verificationMaterial.tlogEntries[${i}].inclusionProof`); 181 } 182 else { 183 if (entry.inclusionProof.checkpoint === undefined) { 184 invalidValues.push(`verificationMaterial.tlogEntries[${i}].inclusionProof.checkpoint`); 185 } 186 } 187 }); 188 } 189 return invalidValues; 190} 191// Necessary for V03 and later bundles 192function validateNoCertificateChain(b) { 193 const invalidValues = []; 194 if (b.verificationMaterial?.content?.$case === 'x509CertificateChain') { 195 invalidValues.push('verificationMaterial.content.$case'); 196 } 197 return invalidValues; 198} 199