@@ -81,6 +81,7 @@ static const char * const cups_jwa_algorithms[CUPS_JWA_MAX] =
8181// Local functions...
8282//
8383
84+ static cups_json_t * find_key (cups_json_t * jwk , cups_jwa_t sigalg , const char * kid );
8485#ifdef HAVE_OPENSSL
8586static BIGNUM * make_bignum (cups_json_t * jwk , const char * key );
8687static void make_bnstring (const BIGNUM * bn , char * buffer , size_t bufsize );
@@ -392,7 +393,7 @@ cupsJWTHasValidSignature(
392393 if (!jwt || !jwt -> signature || !jwk )
393394 return (false);
394395
395- DEBUG_printf ("1cupsJWTHasValidSignature: orig sig(%u) = %02X%02X%02X%02X...%02X%02X%02X%02X" , (unsigned )jwt -> sigsize , jwt -> signature [0 ], jwt -> signature [1 ], jwt -> signature [2 ], jwt -> signature [3 ], jwt -> signature [jwt -> sigsize - 4 ], jwt -> signature [jwt -> sigsize - 3 ], jwt -> signature [jwt -> sigsize - 2 ], jwt -> signature [jwt -> sigsize - 1 ]);
396+ DEBUG_printf ("1cupsJWTHasValidSignature: sigalg=%d, orig sig[%u]=< %02X%02X%02X%02X...%02X%02X%02X%02X>" , jwt -> sigalg , (unsigned )jwt -> sigsize , jwt -> signature [0 ], jwt -> signature [1 ], jwt -> signature [2 ], jwt -> signature [3 ], jwt -> signature [jwt -> sigsize - 4 ], jwt -> signature [jwt -> sigsize - 3 ], jwt -> signature [jwt -> sigsize - 2 ], jwt -> signature [jwt -> sigsize - 1 ]);
396397
397398 switch (jwt -> sigalg )
398399 {
@@ -416,6 +417,7 @@ cupsJWTHasValidSignature(
416417 // Get the message hash...
417418 text = make_string (jwt , false);
418419 text_len = strlen (text );
420+ jwk = find_key (jwk , jwt -> sigalg , jwt -> sigkid );
419421
420422#ifdef HAVE_OPENSSL
421423 hash_len = cupsHashData (cups_jwa_algorithms [jwt -> sigalg ], text , text_len , hash , sizeof (hash ));
@@ -451,6 +453,7 @@ cupsJWTHasValidSignature(
451453 // Get the message hash...
452454 text = make_string (jwt , false);
453455 text_len = strlen (text );
456+ jwk = find_key (jwk , jwt -> sigalg , jwt -> sigkid );
454457
455458#ifdef HAVE_OPENSSL
456459 hash_len = cupsHashData (cups_jwa_algorithms [jwt -> sigalg ], text , text_len , hash , sizeof (hash ));
@@ -523,7 +526,8 @@ cupsJWTImportString(
523526 cups_jwt_t * jwt ; // JWT object
524527 size_t datalen ; // Size of data
525528 char data [65536 ]; // Data
526- const char * alg ; // Signature algorithm, if any
529+ const char * kid , // Key identifier
530+ * alg ; // Signature algorithm, if any
527531
528532
529533 // Allocate a JWT...
@@ -577,8 +581,6 @@ cupsJWTImportString(
577581 // Import JSON...
578582 cups_json_t * json , // JSON data
579583 * json_value , // BASE64URL-encoded string value node
580- * header , // Unprotected header
581- * kid , // Key ID node
582584 * signatures , // Signatures array
583585 * signature ; // Signature element to load
584586 const char * value , // C string value
@@ -664,26 +666,39 @@ cupsJWTImportString(
664666 memcpy (jwt -> signature , data , datalen );
665667 jwt -> sigsize = datalen ;
666668 }
667-
668- if ((header = cupsJSONFind (signature , "header" )) != NULL && (kid = cupsJSONFind (header , "kid" )) != NULL && (value = cupsJSONGetString (kid )) != NULL )
669- jwt -> sigkid = strdup (value );
670669 }
671670
671+ #ifdef DEBUG
672+ if (jwt -> sigsize >= 8 )
673+ DEBUG_printf ("1cupsJWTImportString: signature[%u]=<%02X%02X%02X%02X...%02X%02X%02X%02X>" , (unsigned )jwt -> sigsize , jwt -> signature [0 ], jwt -> signature [1 ], jwt -> signature [2 ], jwt -> signature [3 ], jwt -> signature [jwt -> sigsize - 4 ], jwt -> signature [jwt -> sigsize - 3 ], jwt -> signature [jwt -> sigsize - 2 ], jwt -> signature [jwt -> sigsize - 1 ]);
674+ else if (jwt -> sigsize > 0 )
675+ DEBUG_printf ("1cupsJWTImportString: signature[%u]=<...>" , (unsigned )jwt -> sigsize );
676+ #endif // DEBUG
677+
672678 // Check the algorithm used in the protected header...
673679 if ((alg = cupsJSONGetString (cupsJSONFind (jwt -> jose , "alg" ))) != NULL )
674680 {
675681 cups_jwa_t sigalg ; // Signing algorithm
676682
683+ DEBUG_printf ("1cupsJWTImportString: alg=\"%s\"" , alg );
684+
677685 for (sigalg = CUPS_JWA_NONE ; sigalg < CUPS_JWA_MAX ; sigalg ++ )
678686 {
679687 if (!strcmp (alg , cups_jwa_strings [sigalg ]))
680688 {
681689 jwt -> sigalg = sigalg ;
690+ DEBUG_printf ("1cupsJWTImportString: sigalg=%d" , sigalg );
682691 break ;
683692 }
684693 }
685694 }
686695
696+ if ((kid = cupsJSONGetString (cupsJSONFind (jwt -> jose , "kid" ))) != NULL )
697+ {
698+ DEBUG_printf ("1cupsJWTImportString: kid=\"%s\"" , kid );
699+ jwt -> sigkid = strdup (kid );
700+ }
701+
687702 // Can't have signature with none or no signature for !none...
688703 if ((jwt -> sigalg == CUPS_JWA_NONE ) != (jwt -> sigsize == 0 ))
689704 goto import_error ;
@@ -1193,6 +1208,67 @@ cupsJWTSign(cups_jwt_t *jwt, // I - JWT object
11931208}
11941209
11951210
1211+ //
1212+ // 'find_key()' - Find the key by name or algorithm.
1213+ //
1214+
1215+ static cups_json_t * // O - Key data
1216+ find_key (cups_json_t * jwk , // I - Key set
1217+ cups_jwa_t alg , // I - Signature algorithm
1218+ const char * kid ) // I - Signature key ID
1219+ {
1220+ cups_json_t * keys ; // Array of keys
1221+
1222+
1223+ if ((keys = cupsJSONFind (jwk , "keys" )) != NULL )
1224+ {
1225+ // Full key set, find the key we need to use...
1226+ size_t i , // Looping var
1227+ count ; // Number of keys
1228+ cups_json_t * current ; // Current key
1229+ const char * curkid , // Current key ID
1230+ * curkty ; // Current key type
1231+
1232+ count = cupsJSONGetCount (keys );
1233+
1234+ if (kid )
1235+ {
1236+ // Find the matching key ID
1237+ for (i = 0 ; i < count ; i ++ )
1238+ {
1239+ current = cupsJSONGetChild (keys , i );
1240+ curkid = cupsJSONGetString (cupsJSONFind (current , "kid" ));
1241+
1242+ if (curkid && !strcmp (curkid , kid ))
1243+ {
1244+ DEBUG_printf ("4make_signature: Found matching key \"%s\" at %p." , curkid , (void * )current );
1245+ jwk = current ;
1246+ break ;
1247+ }
1248+ }
1249+ }
1250+ else
1251+ {
1252+ // Find a key that can be used for the specified algorithm
1253+ for (i = 0 ; i < count ; i ++ )
1254+ {
1255+ current = cupsJSONGetChild (keys , i );
1256+ curkty = cupsJSONGetString (cupsJSONFind (current , "kty" ));
1257+
1258+ if (((!curkty || !strcmp (curkty , "ocy" )) && alg >= CUPS_JWA_HS256 && alg <= CUPS_JWA_HS512 ) || (curkty && !strcmp (curkty , "RSA" ) && alg >= CUPS_JWA_RS256 && alg <= CUPS_JWA_RS512 ) || (curkty && !strcmp (curkty , "EC" ) && alg >= CUPS_JWA_ES256 && alg <= CUPS_JWA_ES512 ))
1259+ {
1260+ DEBUG_printf ("4make_signature: Found compatible key \"%s\" at %p." , cupsJSONGetString (cupsJSONFind (current , "kid" )), (void * )current );
1261+ jwk = current ;
1262+ break ;
1263+ }
1264+ }
1265+ }
1266+ }
1267+
1268+ return (jwk );
1269+ }
1270+
1271+
11961272#ifdef HAVE_OPENSSL
11971273//
11981274// 'make_bignum()' - Make a BIGNUM for the specified key.
@@ -1623,7 +1699,6 @@ make_signature(cups_jwt_t *jwt, // I - JWT
16231699 const char * * sigkid ) // IO - Key ID string, if any
16241700{
16251701 bool ret = false; // Return value
1626- cups_json_t * keys ; // Array of keys
16271702 char * text ; // JWS Signing Input
16281703 size_t text_len ; // Length of signing input
16291704#ifdef HAVE_OPENSSL
@@ -1638,52 +1713,12 @@ make_signature(cups_jwt_t *jwt, // I - JWT
16381713#endif // HAVE_OPENSSL
16391714
16401715
1716+ DEBUG_printf ("3make_signature(jwt=%p, alg=%d, jwk=%p, signature=%p, sigsize=%p(%u), sigkid=%p(%s))" , (void * )jwt , alg , (void * )jwk , (void * )signature , (void * )sigsize , (unsigned )* sigsize , (void * )sigkid , * sigkid );
1717+
16411718 // Get text to sign...
16421719 text = make_string (jwt , false);
16431720 text_len = strlen (text );
1644-
1645- if ((keys = cupsJSONFind (jwk , "keys" )) != NULL )
1646- {
1647- // Full key set, find the key we need to use...
1648- size_t i , // Looping var
1649- count ; // Number of keys
1650- cups_json_t * current ; // Current key
1651- const char * curkid , // Current key ID
1652- * curkty ; // Current key type
1653-
1654- count = cupsJSONGetCount (keys );
1655-
1656- if (* sigkid )
1657- {
1658- // Find the matching key ID
1659- for (i = 0 ; i < count ; i ++ )
1660- {
1661- current = cupsJSONGetChild (keys , i );
1662- curkid = cupsJSONGetString (cupsJSONFind (current , "kid" ));
1663-
1664- if (curkid && !strcmp (curkid , * sigkid ))
1665- {
1666- jwk = current ;
1667- break ;
1668- }
1669- }
1670- }
1671- else
1672- {
1673- // Find a key that can be used for the specified algorithm
1674- for (i = 0 ; i < count ; i ++ )
1675- {
1676- current = cupsJSONGetChild (keys , i );
1677- curkty = cupsJSONGetString (cupsJSONFind (current , "kty" ));
1678-
1679- if (((!curkty || !strcmp (curkty , "ocy" )) && alg >= CUPS_JWA_HS256 && alg <= CUPS_JWA_HS512 ) || (curkty && !strcmp (curkty , "RSA" ) && alg >= CUPS_JWA_RS256 && alg <= CUPS_JWA_RS512 ) || (curkty && !strcmp (curkty , "EC" ) && alg >= CUPS_JWA_ES256 && alg <= CUPS_JWA_ES512 ))
1680- {
1681- jwk = current ;
1682- break ;
1683- }
1684- }
1685- }
1686- }
1721+ jwk = find_key (jwk , alg , * sigkid );
16871722
16881723 if (alg >= CUPS_JWA_HS256 && alg <= CUPS_JWA_HS512 )
16891724 {
@@ -1693,6 +1728,8 @@ make_signature(cups_jwt_t *jwt, // I - JWT
16931728 size_t key_len ; // Length of key
16941729 ssize_t hmac_len ; // Length of HMAC
16951730
1731+ DEBUG_puts ("4make_signature: HMAC signature" );
1732+
16961733 // Get key...
16971734 memset (key , 0 , sizeof (key ));
16981735 k = cupsJSONGetString (cupsJSONFind (jwk , "k" ));
@@ -1709,6 +1746,8 @@ make_signature(cups_jwt_t *jwt, // I - JWT
17091746 else if (alg >= CUPS_JWA_RS256 && alg <= CUPS_JWA_RS512 )
17101747 {
17111748 // RSASSA-PKCS1-v1_5 SHA-256/384/512
1749+ DEBUG_puts ("4make_signature: RSA signature" );
1750+
17121751#ifdef HAVE_OPENSSL
17131752 unsigned char hash [128 ]; // SHA-256/384/512 hash
17141753 ssize_t hash_len ; // Length of hash
@@ -1750,6 +1789,8 @@ make_signature(cups_jwt_t *jwt, // I - JWT
17501789 else if (alg >= CUPS_JWA_ES256 && alg <= CUPS_JWA_ES512 )
17511790 {
17521791 // ECDSA P-256 SHA-256/384/512
1792+ DEBUG_puts ("4make_signature: ECDSA signature" );
1793+
17531794 static unsigned sig_sizes [3 ] = // Sizes of signatures
17541795 { 64 , 96 , 132 };
17551796#ifdef HAVE_OPENSSL
@@ -1827,6 +1868,8 @@ make_signature(cups_jwt_t *jwt, // I - JWT
18271868
18281869 done :
18291870
1871+ DEBUG_printf ("4make_signature: Returning %s." , ret ? "true" : "false" );
1872+
18301873 free (text );
18311874
18321875 if (ret )
0 commit comments