/*******************************************************************************
 * Copyright (c) 2007, 2019 IBM Corporation and others.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which accompanies this distribution,
 * and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors: IBM Corporation - initial API and implementation
 ******************************************************************************/
package org.eclipse.osgi.internal.signedcontent;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SignatureException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
import org.eclipse.osgi.signedcontent.SignerInfo;
import org.eclipse.osgi.storage.bundlefile.BundleEntry;
import org.eclipse.osgi.storage.bundlefile.BundleFile;
import org.eclipse.osgi.util.NLS;

public class SignatureBlockProcessor implements SignedContentConstants {
	private final SignedBundleFile signedBundle;
	private List<SignerInfo> signerInfos = new ArrayList<>();
	private Map<String, Object> contentMDResults = new HashMap<>();
	// map of tsa singers keyed by SignerInfo -> {tsa_SignerInfo, signingTime}
	private Map<SignerInfo, Object[]> tsaSignerInfos;
	private final int supportFlags;
	private final SignedBundleHook signedBundleHook;

	public SignatureBlockProcessor(SignedBundleFile signedContent, int supportFlags, SignedBundleHook signedBundleHook) {
		this.signedBundle = signedContent;
		this.supportFlags = supportFlags;
		this.signedBundleHook = signedBundleHook;
	}

	public SignedContentImpl process() throws IOException, InvalidKeyException, SignatureException, CertificateException, NoSuchAlgorithmException, NoSuchProviderException {
		BundleFile wrappedBundleFile = signedBundle.getBundleFile();
		BundleEntry be = wrappedBundleFile.getEntry(META_INF_MANIFEST_MF);
		if (be == null)
			return createUnsignedContent();

		// read all the signature block file names into a list
		Enumeration<String> en = wrappedBundleFile.getEntryPaths(META_INF);
		List<String> signers = new ArrayList<>(2);
		while (en.hasMoreElements()) {
			String name = en.nextElement();
			if ((name.endsWith(DOT_DSA) || name.endsWith(DOT_RSA)) && name.indexOf('/') == name.lastIndexOf('/'))
				signers.add(name);
		}

		// this means the jar is not signed
		if (signers.size() == 0)
			return createUnsignedContent();

		byte manifestBytes[] = readIntoArray(be);
		// process the signers

		for (Iterator<String> iSigners = signers.iterator(); iSigners.hasNext();)
			processSigner(wrappedBundleFile, manifestBytes, iSigners.next());

		// done processing now create a SingedContent to return
		SignerInfo[] allSigners = signerInfos.toArray(new SignerInfo[signerInfos.size()]);
		for (Map.Entry<String, Object> entry : contentMDResults.entrySet()) {
			@SuppressWarnings("unchecked")
			List<Object>[] value = (List<Object>[]) entry.getValue();
			SignerInfo[] entrySigners = value[0].toArray(new SignerInfo[value[0].size()]);
			byte[][] entryResults = value[1].toArray(new byte[value[1].size()][]);
			entry.setValue(new Object[] {entrySigners, entryResults});
		}
		SignedContentImpl result = new SignedContentImpl(allSigners, (supportFlags & SignedBundleHook.VERIFY_RUNTIME) != 0 ? contentMDResults : null);
		result.setContent(signedBundle);
		result.setTSASignerInfos(tsaSignerInfos);
		return result;
	}

	private SignedContentImpl createUnsignedContent() {
		SignedContentImpl result = new SignedContentImpl(new SignerInfo[0], contentMDResults);
		result.setContent(signedBundle);
		return result;
	}

	private void processSigner(BundleFile bf, byte[] manifestBytes, String signer) throws IOException, SignatureException, InvalidKeyException, CertificateException, NoSuchAlgorithmException, NoSuchProviderException {
		BundleEntry be = bf.getEntry(signer);
		byte pkcs7Bytes[] = readIntoArray(be);
		int dotIndex = signer.lastIndexOf('.');
		be = bf.getEntry(signer.substring(0, dotIndex) + DOT_SF);
		byte sfBytes[] = readIntoArray(be);

		// Step 1, verify the .SF file is signed by the private key that corresponds to the public key
		// in the .RSA/.DSA file
		String baseFile = bf.getBaseFile() != null ? bf.getBaseFile().toString() : null;
		PKCS7Processor processor = new PKCS7Processor(pkcs7Bytes, 0, pkcs7Bytes.length, signer, baseFile);
		// call the Step 1 in the Jar File Verification algorithm
		processor.verifySFSignature(sfBytes, 0, sfBytes.length);
		// algorithm used
		String digAlg = getDigAlgFromSF(sfBytes);
		if (digAlg == null)
			throw new SignatureException(NLS.bind(SignedContentMessages.SF_File_Parsing_Error, new String[] {bf.toString()}));
		// get the digest results
		// Process the Step 2 in the Jar File Verification algorithm
		// Get the manifest out of the signature file and make sure
		// it matches MANIFEST.MF
		verifyManifestAndSignatureFile(manifestBytes, sfBytes);

		// create a SignerInfo with the processed information
		SignerInfoImpl signerInfo = new SignerInfoImpl(processor.getCertificates(), null, digAlg);
		if ((supportFlags & SignedBundleHook.VERIFY_RUNTIME) != 0)
			// only populate the manifests digest information for verifying content at runtime
			populateMDResults(manifestBytes, signerInfo);
		signerInfos.add(signerInfo);
		// check for tsa signers
		Certificate[] tsaCerts = processor.getTSACertificates();
		Date signingTime = processor.getSigningTime();
		if (tsaCerts != null && signingTime != null) {
			SignerInfoImpl tsaSignerInfo = new SignerInfoImpl(tsaCerts, null, digAlg);
			if (tsaSignerInfos == null)
				tsaSignerInfos = new HashMap<>(2);
			tsaSignerInfos.put(signerInfo, new Object[] {tsaSignerInfo, signingTime});
		}
	}

	/**
	 * Verify the digest listed in each entry in the .SF file with corresponding section in the manifest
	 * @throws SignatureException
	 */
	private void verifyManifestAndSignatureFile(byte[] manifestBytes, byte[] sfBytes) throws SignatureException {

		String sf = new String(sfBytes, StandardCharsets.UTF_8);
		sf = stripContinuations(sf);

		// check if there -Digest-Manfiest: header in the file
		int off = sf.indexOf(digestManifestSearch);
		if (off != -1) {
			int start = sf.lastIndexOf('\n', off);
			String manifestDigest = null;
			if (start != -1) {
				// Signature-Version has to start the file, so there
				// should always be a newline at the start of
				// Digest-Manifest
				String digestName = sf.substring(start + 1, off);
				if (digestName.equalsIgnoreCase(MD5_STR))
					manifestDigest = calculateDigest(getMessageDigest(MD5_STR), manifestBytes);
				else if (digestName.equalsIgnoreCase(SHA1_STR))
					manifestDigest = calculateDigest(getMessageDigest(SHA1_STR), manifestBytes);
				else
					manifestDigest = calculateDigest(getMessageDigest(digestName), manifestBytes);
				off += digestManifestSearchLen;

				// find out the index of first '\n' after the -Digest-Manifest:
				int nIndex = sf.indexOf('\n', off);
				String digestValue = sf.substring(off, nIndex - 1);

				// check if the the computed digest value of manifest file equals to the digest value in the .sf file
				if (!digestValue.equals(manifestDigest)) {
					SignatureException se = new SignatureException(NLS.bind(SignedContentMessages.Security_File_Is_Tampered, new String[] {signedBundle.getBaseFile().toString()}));
					signedBundleHook.log(se.getMessage(), FrameworkLogEntry.ERROR, se);
					throw se;
				}
			}
		}
	}

	private void populateMDResults(byte mfBuf[], SignerInfo signerInfo) {
		// need to make a string from the MF file data bytes
		String mfStr = new String(mfBuf, StandardCharsets.UTF_8);

		// start parsing each entry in the MF String
		int entryStartOffset = mfStr.indexOf(MF_ENTRY_NEWLN_NAME);
		int length = mfStr.length();

		while ((entryStartOffset != -1) && (entryStartOffset < length)) {

			// get the start of the next 'entry', i.e. the end of this entry
			int entryEndOffset = mfStr.indexOf(MF_ENTRY_NEWLN_NAME, entryStartOffset + 1);
			if (entryEndOffset == -1) {
				// if there is no next entry, then the end of the string
				// is the end of this entry
				entryEndOffset = mfStr.length();
			}

			// get the string for this entry only, since the entryStartOffset
			// points to the '\n' before the 'Name: ' we increase it by 1
			// this is guaranteed to not go past end-of-string and be less
			// then entryEndOffset.
			String entryStr = mfStr.substring(entryStartOffset + 1, entryEndOffset);
			entryStr = stripContinuations(entryStr);

			// increment the offset to the ending entry for the next iteration of the loop ...
			entryStartOffset = entryEndOffset;

			// entry points to the start of the next 'entry'
			String entryName = getEntryFileName(entryStr);

			// if we could retrieve an entry name, then we will extract
			// digest type list, and the digest value list
			if (entryName != null) {
				String aDigestLine = getDigestLine(entryStr, signerInfo.getMessageDigestAlgorithm());

				if (aDigestLine != null) {
					String msgDigestAlgorithm = getDigestAlgorithmFromString(aDigestLine);
					if (!msgDigestAlgorithm.equalsIgnoreCase(signerInfo.getMessageDigestAlgorithm()))
						continue; // TODO log error?
					byte digestResult[] = getDigestResultsList(aDigestLine);

					//
					// only insert this entry into the table if its
					// "well-formed",
					// i.e. only if we could extract its name, digest types, and
					// digest-results
					//
					// sanity check, if the 2 lists are non-null, then their
					// counts must match
					//
					//					if ((msgDigestObj != null) && (digestResultsList != null)
					//							&& (1 != digestResultsList.length)) {
					//						throw new RuntimeException(
					//								"Errors occurs when parsing the manifest file stream!"); //$NON-NLS-1$
					//					}
					@SuppressWarnings("unchecked")
					List<Object>[] mdResult = (List<Object>[]) contentMDResults.get(entryName);
					if (mdResult == null) {
						@SuppressWarnings("unchecked")
						List<Object>[] arrayLists = new ArrayList[2];
						mdResult = arrayLists;
						mdResult[0] = new ArrayList<>();
						mdResult[1] = new ArrayList<>();
						contentMDResults.put(entryName, mdResult);
					}
					mdResult[0].add(signerInfo);
					mdResult[1].add(digestResult);
				} // could get lines of digest entries in this MF file entry
			} // could retrieve entry name
		}
	}

	private static byte[] getDigestResultsList(String digestLines) {
		byte resultsList[] = null;
		if (digestLines != null) {
			// for each digest-line retrieve the digest result
			// for (int i = 0; i < digestLines.length; i++) {
			String sDigestLine = digestLines;
			int indexDigest = sDigestLine.indexOf(MF_DIGEST_PART);
			indexDigest += MF_DIGEST_PART.length();
			// if there is no data to extract for this digest value
			// then we will fail...
			if (indexDigest >= sDigestLine.length()) {
				resultsList = null;
				// break;
			}
			// now attempt to base64 decode the result
			String sResult = sDigestLine.substring(indexDigest);
			try {
				resultsList = Base64.decode(sResult.getBytes());
			} catch (Throwable t) {
				// malformed digest result, no longer processing this entry
				resultsList = null;
			}
		}
		return resultsList;
	}

	private static String getDigestAlgorithmFromString(String digestLines) {
		if (digestLines != null) {
			// String sDigestLine = digestLines[i];
			int indexDigest = digestLines.indexOf(MF_DIGEST_PART);
			String sDigestAlgType = digestLines.substring(0, indexDigest);
			if (sDigestAlgType.equalsIgnoreCase(MD5_STR)) {
				// remember the "algorithm type"
				return MD5_STR;
			} else if (sDigestAlgType.equalsIgnoreCase(SHA1_STR)) {
				// remember the "algorithm type" object
				return SHA1_STR;
			} else {
				return sDigestAlgType;
			}
		}
		return null;
	}

	private static String getEntryFileName(String manifestEntry) {
		// get the beginning of the name
		int nameStart = manifestEntry.indexOf(MF_ENTRY_NAME);
		if (nameStart == -1) {
			return null;
		}
		// check where the name ends
		int nameEnd = manifestEntry.indexOf('\n', nameStart);
		if (nameEnd == -1) {
			return null;
		}
		// if there is a '\r' before the '\n', then we'll strip it
		if (manifestEntry.charAt(nameEnd - 1) == '\r') {
			nameEnd--;
		}
		// get to the beginning of the actual name...
		nameStart += MF_ENTRY_NAME.length();
		if (nameStart >= nameEnd) {
			return null;
		}
		return manifestEntry.substring(nameStart, nameEnd);
	}

	/**
	 * Returns the Base64 encoded digest of the passed set of bytes.
	 */
	private static String calculateDigest(MessageDigest digest, byte[] bytes) {
		return new String(Base64.encode(digest.digest(bytes)), StandardCharsets.UTF_8);
	}

	synchronized MessageDigest getMessageDigest(String algorithm) {
		try {
			return MessageDigest.getInstance(algorithm);
		} catch (NoSuchAlgorithmException e) {
			signedBundleHook.log(e.getMessage(), FrameworkLogEntry.ERROR, e);
		}
		return null;
	}

	/**
	 * Read the .SF file abd assuming that same digest algorithm will be used through out the whole
	 * .SF file.  That digest algorithm name in the last entry will be returned.
	 *
	 * @param SFBuf			a .SF file in bytes
	 * @return				the digest algorithm name used in the .SF file
	 */
	private static String getDigAlgFromSF(byte SFBuf[]) {
		// need to make a string from the MF file data bytes
		String mfStr = new String(SFBuf, StandardCharsets.UTF_8);
		String entryStr = null;

		// start parsing each entry in the MF String
		int entryStartOffset = mfStr.indexOf(MF_ENTRY_NEWLN_NAME);
		int length = mfStr.length();

		if ((entryStartOffset != -1) && (entryStartOffset < length)) {

			// get the start of the next 'entry', i.e. the end of this entry
			int entryEndOffset = mfStr.indexOf(MF_ENTRY_NEWLN_NAME, entryStartOffset + 1);
			if (entryEndOffset == -1) {
				// if there is no next entry, then the end of the string
				// is the end of this entry
				entryEndOffset = mfStr.length();
			}

			// get the string for this entry only, since the entryStartOffset
			// points to the '\n' before the 'Name: ' we increase it by 1
			// this is guaranteed to not go past end-of-string and be less
			// then entryEndOffset.
			entryStr = mfStr.substring(entryStartOffset + 1, entryEndOffset);
			entryStr = stripContinuations(entryStr);
		}

		if (entryStr != null) {
			// process the entry to retrieve the digest algorith name
			String digestLine = getDigestLine(entryStr, null);

			// throw parsing
			return getMessageDigestName(digestLine);
		}
		return null;
	}

	/**
	 *
	 * @param manifestEntry contains a single MF file entry of the format
	 * 				   "Name: foo"
	 * 				   "MD5-Digest: [base64 encoded MD5 digest data]"
	 * 				   "SHA1-Digest: [base64 encoded SHA1 digest dat]"
	 *
	 * @param	desireDigestAlg	a string representing the desire digest value to be returned if there are
	 * 							multiple digest lines.
	 * 							If this value is null, return whatever digest value is in the entry.
	 *
	 * @return this function returns a digest line based on the desire digest algorithm value
	 * 		   (since only MD5 and SHA1 are recognized here),
	 * 		   or a 'null' will be returned if none of the digest algorithms
	 * 		   were recognized.
	 */
	private static String getDigestLine(String manifestEntry, String desireDigestAlg) {
		String result = null;

		// find the first digest line
		int indexDigest = manifestEntry.indexOf(MF_DIGEST_PART);
		// if we didn't find any digests at all, then we are done
		if (indexDigest == -1)
			return null;

		// while we continue to find digest entries
		// note: in the following loop we bail if any of the lines
		//		 look malformed...
		while (indexDigest != -1) {
			// see where this digest line begins (look to left)
			int indexStart = manifestEntry.lastIndexOf('\n', indexDigest);
			if (indexStart == -1)
				return null;
			// see where it ends (look to right)
			int indexEnd = manifestEntry.indexOf('\n', indexDigest);
			if (indexEnd == -1)
				return null;
			// strip off ending '\r', if any
			int indexEndToUse = indexEnd;
			if (manifestEntry.charAt(indexEndToUse - 1) == '\r')
				indexEndToUse--;
			// indexStart points to the '\n' before this digest line
			int indexStartToUse = indexStart + 1;
			if (indexStartToUse >= indexEndToUse)
				return null;

			// now this may be a valid digest line, parse it a bit more
			// to see if this is a preferred digest algorithm
			String digestLine = manifestEntry.substring(indexStartToUse, indexEndToUse);
			String digAlg = getMessageDigestName(digestLine);
			if (desireDigestAlg != null) {
				if (desireDigestAlg.equalsIgnoreCase(digAlg))
					return digestLine;
			}

			// desireDigestAlg is null, always return the digestLine
			result = digestLine;

			// iterate to next digest line in this entry
			indexDigest = manifestEntry.indexOf(MF_DIGEST_PART, indexEnd);
		}

		// if we couldn't find any digest lines, then we are done
		return result;
	}

	/**
	 * Return the Message Digest name
	 *
	 * @param digLine		the message digest line is in the following format.  That is in the
	 * 						following format:
	 * 								DIGEST_NAME-digest: digest value
	 * @return				a string representing a message digest.
	 */
	private static String getMessageDigestName(String digLine) {
		String rtvValue = null;
		if (digLine != null) {
			int indexDigest = digLine.indexOf(MF_DIGEST_PART);
			if (indexDigest != -1) {
				rtvValue = digLine.substring(0, indexDigest);
			}
		}
		return rtvValue;
	}

	private static String stripContinuations(String entry) {
		if (entry.indexOf("\n ") < 0 && entry.indexOf("\r ") < 0) //$NON-NLS-1$//$NON-NLS-2$
			return entry;
		StringBuilder buffer = new StringBuilder(entry);
		removeAll(buffer, "\r\n "); //$NON-NLS-1$
		removeAll(buffer, "\n "); //$NON-NLS-1$
		removeAll(buffer, "\r "); //$NON-NLS-1$
		return buffer.toString();
	}

	private static StringBuilder removeAll(StringBuilder buffer, String toRemove) {
		int index = buffer.indexOf(toRemove);
		int length = toRemove.length();
		while (index > 0) {
			buffer.replace(index, index + length, ""); //$NON-NLS-1$
			index = buffer.indexOf(toRemove, index);
		}
		return buffer;
	}

	private static byte[] readIntoArray(BundleEntry be) throws IOException {
		int size = (int) be.getSize();
		InputStream is = be.getInputStream();
		try {
			byte b[] = new byte[size];
			int rc = readFully(is, b);
			if (rc != size) {
				throw new IOException("Couldn't read all of " + be.getName() + ": " + rc + " != " + size); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			}
			return b;
		} finally {
			try {
				is.close();
			} catch (IOException e) {
				// do nothing;
			}
		}
	}

	private static int readFully(InputStream is, byte b[]) throws IOException {
		int count = b.length;
		int offset = 0;
		int rc;
		while ((rc = is.read(b, offset, count)) > 0) {
			count -= rc;
			offset += rc;
		}
		return offset;
	}
}
