Network Security Services は、Firefox、Thunderbird、いくつかの Linux システムコンポーネントの基盤となるライブラリで、Firefox の WebCrypto もこの上で動いています。NSS は PKCS#11 を介して動作します。鍵はトークン(組み込みの softoken、またはスマートカードや HSM)の中にあり、その上のすべての層が PK11_* 関数を呼び出します。ここに挙げる事実は、Alpine 3.24.2 のパッケージである NSS 3.124 を鍵データベースなしで初期化して(NSS_NoDB_Init)確認したものです。
ECDSA には、異なるエンコーディングを生成する層が 2 つあります。cryptohi の SEC_SignData と VFY_VerifyData はメッセージをハッシュ化し、X.509、CMS、OpenSSL が想定する形式である DER を使います。PK11_Sign と PK11_Verify はダイジェストを受け取り、生の r‖s 形式(P-256 では 64 バイト)を使います。この 2 つを混在させるのが NSS の典型的な間違いです。DER ⇄ 生形式の変換ツールで変換してください。また、PK11_Sign は P-256 で 64 バイトのダイジェストも受け付け、その先頭 32 バイトに署名したため、曲線に合ったダイジェストを渡してください。
nonce はランダムで(同じメッセージの 2 つの署名は異なりました)、s は正規化されません。high-S の署名も検証を通りました。P-384 の鍵で SHA-256 を使う ECDSA の署名と検証ができたため、ハッシュは曲線に結び付けられていません。失敗の種類は区別できます。VFY_VerifyData が SECFailure を返したあと、PORT_GetError() は、生の署名や途中で切れた署名に対しては SEC_ERROR_BAD_DER を、別のデータに対する有効な署名に対しては SEC_ERROR_BAD_SIGNATURE を報告します。
softoken が鍵を生成できたのは P-256、P-384、P-521 だけで、P-224 と secp256k1 は SEC_ERROR_INVALID_KEY で失敗しました。Ed25519 は CKM_EC_EDWARDS_KEY_PAIR_GEN と CKM_EDDSA で動作しますが、Ed448 は動作しません。ML-KEM-768 のカプセル化とデカプセル化は一通り動作します(PK11_Encapsulate、PK11_Decapsulate)。一方、ヘッダーでは ML-DSA のメカニズムが宣言されていますが、このビルドの softoken はそれを提供していません。KEM は ML-KEM ツールで比較してください。