This repository has been archived by the owner on Sep 19, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
282 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
/* | ||
* Copyright (c) 2024 Cisco and/or its affiliates. All rights reserved. | ||
* | ||
* SPDX-License-Identifier: MIT OR GPL-2.0-only | ||
* | ||
* Licensed under the MIT license <LICENSE.MIT or https://opensource.org/licenses/MIT> or the GPLv2 license | ||
* <LICENSE.GPL or https://opensource.org/license/gpl-2-0>, at your option. This file may not be copied, | ||
* modified, or distributed except according to those terms. | ||
*/ | ||
|
||
#include <crypto/hash.h> | ||
|
||
static struct shash_desc *init_sdesc(struct crypto_shash *alg) | ||
{ | ||
struct shash_desc *sdesc; | ||
int size; | ||
|
||
size = sizeof(struct shash_desc) + crypto_shash_descsize(alg); | ||
sdesc = kmalloc(size, GFP_KERNEL); | ||
if (!sdesc) | ||
return ERR_PTR(-ENOMEM); | ||
sdesc->tfm = alg; | ||
return sdesc; | ||
} | ||
|
||
u8 *hmac_sha256(const u8 *data, unsigned data_len, const char *key, unsigned key_len) | ||
{ | ||
const char *hash_alg_name = "hmac(sha256)"; | ||
struct crypto_shash *shash; | ||
int err; | ||
|
||
shash = crypto_alloc_shash(hash_alg_name, 0, 0); | ||
|
||
if (IS_ERR(shash)) | ||
{ | ||
printk(KERN_ERR "can't alloc alg %s\n", hash_alg_name); | ||
return PTR_ERR(shash); | ||
} | ||
|
||
err = crypto_shash_setkey(shash, key, key_len); | ||
if (err < 0) | ||
{ | ||
printk(KERN_ERR "can't set key\n"); | ||
crypto_free_shash(shash); | ||
return ERR_PTR(err); | ||
} | ||
|
||
struct shash_desc *desc = init_sdesc(shash); | ||
|
||
u8 *out = kmalloc(crypto_shash_digestsize(shash), GFP_KERNEL); | ||
|
||
err = crypto_shash_digest(desc, data, data_len, out); | ||
|
||
if (err < 0) | ||
{ | ||
printk(KERN_ERR "can't digest\n"); | ||
crypto_free_shash(shash); | ||
kfree(out); | ||
kfree(desc); | ||
return ERR_PTR(err); | ||
} | ||
|
||
crypto_free_shash(shash); | ||
kfree(desc); | ||
|
||
return out; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/* | ||
* Copyright (c) 2024 Cisco and/or its affiliates. All rights reserved. | ||
* | ||
* SPDX-License-Identifier: MIT OR GPL-2.0-only | ||
* | ||
* Licensed under the MIT license <LICENSE.MIT or https://opensource.org/licenses/MIT> or the GPLv2 license | ||
* <LICENSE.GPL or https://opensource.org/license/gpl-2-0>, at your option. This file may not be copied, | ||
* modified, or distributed except according to those terms. | ||
*/ | ||
|
||
#ifndef crypto_h | ||
#define crypto_h | ||
|
||
char *hmac_sha256(const char *data, unsigned data_len, const char *key); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
/* | ||
* Copyright (c) 2024 Cisco and/or its affiliates. All rights reserved. | ||
* | ||
* SPDX-License-Identifier: MIT OR GPL-2.0-only | ||
* | ||
* Licensed under the MIT license <LICENSE.MIT or https://opensource.org/licenses/MIT> or the GPLv2 license | ||
* <LICENSE.GPL or https://opensource.org/license/gpl-2-0>, at your option. This file may not be copied, | ||
* modified, or distributed except according to those terms. | ||
*/ | ||
|
||
#include "base64.h" | ||
#include "crypto.h" | ||
#include "jwt.h" | ||
#include "json.h" | ||
#include <linux/slab.h> | ||
|
||
jwt_t *jwt_parse(const char *jwt, const char *secret) | ||
{ | ||
jwt_t *j = kzalloc(sizeof(jwt_t), GFP_KERNEL); | ||
if (!j) | ||
{ | ||
return NULL; | ||
} | ||
|
||
char *header_end = strchr(jwt, '.'); | ||
|
||
if (!header_end) | ||
{ | ||
kfree(j); | ||
return NULL; | ||
} | ||
|
||
char *header_json = kzalloc(256, GFP_KERNEL); | ||
if (!header_json) | ||
{ | ||
kfree(j); | ||
return NULL; | ||
} | ||
|
||
int err = base64_decode(header_json, 256, jwt, header_end - jwt); | ||
if (err < 0) | ||
{ | ||
kfree(j); | ||
kfree(header_json); | ||
return NULL; | ||
} | ||
|
||
printk(KERN_INFO "header_json: '%s'\n", header_json); | ||
|
||
JSON_Value *header = json_parse_string(header_json); | ||
if (!header) | ||
{ | ||
kfree(j); | ||
kfree(header_json); | ||
return NULL; | ||
} | ||
|
||
JSON_Object *header_obj = json_value_get_object(header); | ||
|
||
j->alg = json_object_get_string(header_obj, "alg"); | ||
j->typ = json_object_get_string(header_obj, "typ"); | ||
|
||
char *payload_end = strchr(header_end + 1, '.'); | ||
if (!payload_end) | ||
{ | ||
kfree(j); | ||
kfree(header_json); | ||
json_value_free(header); | ||
return NULL; | ||
} | ||
|
||
char *payload_json = kzalloc(256, GFP_KERNEL); | ||
if (!payload_json) | ||
{ | ||
kfree(j); | ||
kfree(header_json); | ||
json_value_free(header); | ||
return NULL; | ||
} | ||
|
||
err = base64_decode(payload_json, 256, header_end + 1, payload_end - header_end - 1); | ||
if (err < 0) | ||
{ | ||
kfree(j); | ||
kfree(header_json); | ||
kfree(payload_json); | ||
json_value_free(header); | ||
return NULL; | ||
} | ||
|
||
printk(KERN_INFO "payload_json: '%s'\n", payload_json); | ||
|
||
JSON_Value *payload = json_parse_string(payload_json); | ||
if (!payload) | ||
{ | ||
kfree(j); | ||
kfree(header_json); | ||
kfree(payload_json); | ||
json_value_free(header); | ||
return NULL; | ||
} | ||
|
||
JSON_Object *payload_obj = json_value_get_object(payload); | ||
|
||
j->iss = json_object_get_string(payload_obj, "iss"); | ||
j->sub = json_object_get_string(payload_obj, "sub"); | ||
j->aud = json_object_get_string(payload_obj, "aud"); | ||
j->exp = json_object_get_number(payload_obj, "exp"); | ||
|
||
// signature parsing | ||
char *signature = payload_end + 1; | ||
|
||
printk("calculating hash for [%d bytes]: %.*s", payload_end - jwt, payload_end - jwt, jwt); | ||
|
||
char *hash = hmac_sha256(jwt, payload_end - jwt, secret); | ||
if (!hash) | ||
{ | ||
printk(KERN_ERR "failed to calculate hmac"); | ||
|
||
kfree(j); | ||
kfree(header_json); | ||
kfree(payload_json); | ||
json_value_free(header); | ||
|
||
return NULL; | ||
} | ||
|
||
char hash_base64[256]; | ||
|
||
int bytes = base64_encode(hash_base64, 256, hash, 32); | ||
|
||
if (bytes < 0) | ||
{ | ||
printk(KERN_ERR "failed to base64 encode signature"); | ||
|
||
kfree(j); | ||
kfree(header_json); | ||
kfree(payload_json); | ||
json_value_free(header); | ||
|
||
return NULL; | ||
} | ||
|
||
printk("signature [%d bytes]: %s", strlen(signature), signature); | ||
printk("hash_base64 [%d bytes]: %s", bytes, hash_base64); | ||
|
||
return j; | ||
} | ||
|
||
void jwt_free(jwt_t *jwt) | ||
{ | ||
kfree(jwt); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/* | ||
* Copyright (c) 2024 Cisco and/or its affiliates. All rights reserved. | ||
* | ||
* SPDX-License-Identifier: MIT OR GPL-2.0-only | ||
* | ||
* Licensed under the MIT license <LICENSE.MIT or https://opensource.org/licenses/MIT> or the GPLv2 license | ||
* <LICENSE.GPL or https://opensource.org/license/gpl-2-0>, at your option. This file may not be copied, | ||
* modified, or distributed except according to those terms. | ||
*/ | ||
|
||
#ifndef jwt_h | ||
#define jwt_h | ||
|
||
#include "jwt.h" | ||
|
||
typedef struct jwt { | ||
char *alg; | ||
char *typ; | ||
|
||
char *iss; | ||
char *sub; | ||
char *aud; | ||
u64 exp; | ||
|
||
} jwt_t; | ||
|
||
jwt_t *jwt_parse(const char *jwt, const char *secret); | ||
void jwt_free(jwt_t *jwt); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters