Add script to patch unmaintained dependency projects

Cose-c is an unmaintained project but is a dependency project for
open-dice. With this change, we can now setup patches to any dependency
project if the pull request in upstream project is not moving anywhere.

Bug: 476101020
Change-Id: Ib52308f0ba7c86484f48d03e5fdfbc78199bfb1b
Reviewed-on: https://pigweed-review.googlesource.com/c/open-dice/+/374252
diff --git a/README.md b/README.md
index 3e78434..102d12b 100644
--- a/README.md
+++ b/README.md
@@ -56,6 +56,7 @@
 ```bash
 $ git submodule update --init --recursive
 $ source bootstrap.sh
+$ ./apply_local_patches.sh
 $ gn gen out
 ```
 
diff --git a/apply_local_patches.sh b/apply_local_patches.sh
new file mode 100755
index 0000000..bbfbe1a
--- /dev/null
+++ b/apply_local_patches.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+
+# Copyright 2026 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+# This script needs to be executed after third party source code is synced.
+
+set -eu
+
+THIRD_PARTY_ROOT="$(pwd)/third_party"
+
+# Add new patched projects here with a space. Eg: "cose-c boringssl"
+PATCHED_PROJECTS="cose-c"
+
+for project in $PATCHED_PROJECTS; do
+  PROJECT_ROOT="$THIRD_PARTY_ROOT/$project"
+  PROJECT_SRC="$PROJECT_ROOT/src"
+  PATCHES_FOLDER="$PROJECT_ROOT/patches"
+
+  # Double-check that the submodule has been checked out.
+  if [ "$(find "$PROJECT_SRC/." -print | head -n 2 | wc -l)" -le 1 ]; then
+    echo "Error: $PROJECT_SRC is empty."
+    echo "Did you forget to initialize the git submodules?"
+    echo "To setup the git submodules run:"
+    echo "  git submodule update --init --recursive"
+    exit 1
+  fi
+
+  if [ -d "$PATCHES_FOLDER" ] && \
+       [ "$(find "$PATCHES_FOLDER/." -print | head -n 2 | wc -l)" -gt 1 ]; then
+    echo "Applying patches from $project"
+    git -C "$PROJECT_SRC" am "$PATCHES_FOLDER"/*
+  else
+    echo "No patches to apply for $project"
+  fi
+done
+
+echo "Patching complete."
diff --git a/third_party/cose-c/patches/0001-Add-MLDSA-reference-implementation.patch b/third_party/cose-c/patches/0001-Add-MLDSA-reference-implementation.patch
new file mode 100644
index 0000000..d3199a1
--- /dev/null
+++ b/third_party/cose-c/patches/0001-Add-MLDSA-reference-implementation.patch
@@ -0,0 +1,104 @@
+From 3fb04ee08f39c22f8a791b233964db4d1a6e8a3a Mon Sep 17 00:00:00 2001
+From: Vikram Gaur <vikramgaur@google.com>
+Date: Thu, 05 Feb 2026 15:38:21 -0800
+Subject: [PATCH] Add ML-DSA support
+
+Change-Id: I6c9f047a7b0b560d5606c19663aee6265b55d524
+---
+
+diff --git a/include/cose/cose.h b/include/cose/cose.h
+index c9a5783..824cb8e 100644
+--- a/include/cose/cose.h
++++ b/include/cose/cose.h
+@@ -160,7 +160,10 @@
+ 
+ 	COSE_Algorithm_ECDSA_SHA_256 = -7,
+ 	COSE_Algorithm_ECDSA_SHA_384 = -35,
+-	COSE_Algorithm_ECDSA_SHA_512 = -36
++	COSE_Algorithm_ECDSA_SHA_512 = -36,
++
++	COSE_Algorithm_MLDSA_65 = -49,
++	COSE_Algorithm_MLDSA_87 = -50
+ } COSE_Algorithms;
+ 
+ typedef enum {
+@@ -198,6 +201,7 @@
+ 	COSE_Key_Type_OKP = 1,
+ 	COSE_Key_Type_EC2 = 2,
+ 	COSE_Key_Type_OCTET = 4,
++	COSE_Key_Type_AKP = 7,
+ 	COSE_Key_Type = 1,
+ 	COSE_Key_ID = 2,
+ 	COSE_Parameter_KID = 4,
+@@ -205,7 +209,8 @@
+ 	COSE_Key_EC2_X = -2,
+ 	COSE_Key_EC2_Y = -3,
+ 	COSE_Key_OPK_Curve = -1,
+-	COSE_Key_OPK_X = -2
++	COSE_Key_OPK_X = -2,
++	COSE_Key_AKP_Pub = -1
+ } COSE_Constants;
+ 
+ typedef enum {
+diff --git a/src/Sign1.cpp b/src/Sign1.cpp
+index efd7775..d52c98e 100644
+--- a/src/Sign1.cpp
++++ b/src/Sign1.cpp
+@@ -572,6 +572,14 @@
+ 			break;
+ #endif
+ 
++#ifdef USE_MLDSA
++		case COSE_Algorithm_MLDSA_65:
++		case COSE_Algorithm_MLDSA_87:
++			f = MLDSA_Sign(&pSigner->m_message, INDEX_SIGNATURE + 1, pKey,
++				pbToSign, cbToSign, perr);
++			break;
++#endif
++
+ 		default:
+ 			FAIL_CONDITION(COSE_ERR_UNKNOWN_ALGORITHM);
+ 	}
+@@ -658,6 +666,16 @@
+ 			break;
+ #endif
+ 
++#ifdef USE_MLDSA
++		case COSE_Algorithm_MLDSA_65:
++		case COSE_Algorithm_MLDSA_87:
++			if (!MLDSA_Verify(&pSign->m_message, INDEX_SIGNATURE + 1, pKey,
++					pbToSign, cbToSign, perr)) {
++				goto errorReturn;
++			}
++			break;
++#endif
++
+ 		default:
+ 			FAIL_CONDITION(COSE_ERR_UNKNOWN_ALGORITHM);
+ 			break;
+diff --git a/src/cose_crypto.h b/src/cose_crypto.h
+index 4081296..12d4578 100644
+--- a/src/cose_crypto.h
++++ b/src/cose_crypto.h
+@@ -194,6 +194,21 @@
+ 	size_t cbToSign,
+ 	cose_errback* perr);
+ 
++#ifdef USE_MLDSA
++bool MLDSA_Sign(COSE* pSigner,
++	int index,
++	COSE_KEY* pKey,
++	const byte* rgbToSign,
++	size_t cbToSign,
++	cose_errback* perr);
++bool MLDSA_Verify(COSE* pSigner,
++	int index,
++	COSE_KEY* pKey,
++	const byte* rgbToSign,
++	size_t cbToSign,
++	cose_errback* perr);
++#endif
++
+ /**
+  *  Generate random bytes in a buffer
+  *