%% %% This is file `cvss.ins', %% generated with the docstrip utility. %% %% The original source files were: %% %% cvss.dtx (with options: `install') %% ---------------------------------------------------------------- %% cvss --- A package to compute and display CVSS base scores %% E-mail: pierre@vivegnis.be %% Released under the LaTeX Project Public License v1.3c or later %% See http://www.latex-project.org/lppl.txt %% ---------------------------------------------------------------- %% \input docstrip.tex \keepsilent \askforoverwritefalse \preamble ---------------------------------------------------------------- cvss --- A package to compute and display CVSS base scores E-mail: pierre@vivegnis.be Released under the LaTeX Project Public License v1.3c or later See http://www.latex-project.org/lppl.txt ---------------------------------------------------------------- \endpreamble \postamble Copyright (C) 2022 by Pierre VIVEGNIS This work may be distributed and/or modified under the conditions of the LaTeX Project Public License (LPPL), either version 1.3c of this license or (at your option) any later version. The latest version of this license is in the file: http://www.latex-project.org/lppl.txt This work is "maintained" (as per LPPL maintenance status) by Pierre VIVEGNIS. This work consists of the file cvss.dtx and the derived files cvss.ins, cvss.pdf and cvss.sty. \endpostamble \usedir{tex/latex/cvss} \generate{ \file{\jobname.sty}{\from{\jobname.dtx}{package}} } \endbatchfile % \begin{syntax} % \end{function} % \begin{syntax} % \cs{cvssLevel} \Arg{CVSS string} % \end{syntax} % \begin{syntax} % \cs{cvssLevelpretty} \Arg{CVSS string} % \end{syntax} % \begin{syntax} % \cs{cvssTag} \Arg{CVSS string} % \end{syntax} % \begin{syntax} % \cs{category} \Arg{CVSS score} % \end{syntax} %%\category{9.9} \RequirePackage{expl3} \RequirePackage[skins]{tcolorbox} \tcbuselibrary{xparse} \RequirePackage{xstring} \RequirePackage{hyperref} \def\scoreLow{0.1} \def\scoreMed{4.0} \def\scoreHigh{7.0} \def\scoreCrit{9.0} \definecolor{color@cvss@None}{RGB}{83, 170, 51} \definecolor{color@cvss@Low}{RGB}{255, 203, 13} \definecolor{color@cvss@Medium}{RGB}{249, 160, 9} \definecolor{color@cvss@High}{RGB}{223, 61, 3} \definecolor{color@cvss@Critical}{RGB}{204, 5, 0} \ExplSyntaxOn \cs_new:Npn \__CVSS_roundup:n #1 { \fp_eval:n { ceil(#1,1) } \fp_compare:nT { ceil(#1,1)=ceil(#1,0) } {.0} } \msg_new:nnn { CVSS } { invalid-option }{ Value~'#2'~invalid~for~#1~#3.} \msg_new:nnn { CVSS } { invalid-structure } { CVSS~metric~#1~is~not~correct~(#2)~#3.} \msg_new:nnn { CVSS } { invalid-length } { CVSS~vector~"#1"~is~badly~formatted~#2.} \msg_new:nnn { CVSS } { wrong-version } { Wrong~CVSS~version~(#2)~#3.} \cs_new:Npn \__CVSS_parseAV:n #1 { \str_case_e:nnF {#1} { { N } { 0.85 } % Network { A } { 0.62 } % Adjacent { L } { 0.55 } % Local { P } { 0.2 } % Physical } { \msg_error:nnxxx { CVSS } { invalid-option } { parseAV } {#1} {\msg_line_context:} } } \cs_new:Npn \__CVSS_parseAC:n #1 { \str_case_e:nnF {#1} { { H } { 0.44 } % High { L } { 0.77 } % Low } { \msg_error:nnxxx { CVSS } { invalid-option } { parseAC } {#1} {\msg_line_context:} } } \cs_new:Npn \__CVSS_parsePRScopeUnchanged:n #1 { \str_case_e:nnF {#1} { { N } { 0.85 } % None { L } { 0.62 } % Low { H } { 0.27 } % High } { \msg_error:nnxxx { CVSS } { invalid-option } { parsePRScopeUnchanged } {#1} {\msg_line_context:} } } \cs_new:Npn \__CVSS_parsePRScopeChanged:n #1 { \str_case_e:nnF {#1} { { N } { 0.85 } % None { L } { 0.68 } % Low { H } { 0.50 } % High } { \msg_error:nnxxx { CVSS } { invalid-option } { parsePRScopeChanged } {#1} {\msg_line_context:} } } \cs_new:Npn \__CVSS_parsePR:nn #1#2 { % #1 Privilege Required % #2 Scope \str_case_e:nnF {#2} { { U } { \exp_args:Ne \__CVSS_parsePRScopeUnchanged:n {#1} } { C } { \exp_args:Ne \__CVSS_parsePRScopeChanged:n {#1} } } { \msg_error:nnxxx { CVSS } { invalid-option } { parsePR } {#1} {\msg_line_context:} } } \cs_new:Npn \__CVSS_parseUI:n #1 { \str_case_e:nnF {#1} { { N } { 0.85 } % None { R } { 0.62 } % Required } { \msg_error:nnxxx { CVSS } { invalid-option } { parseUI } {#1} {\msg_line_context:} } } \cs_new:Npn \__CVSS_parseCIA:n #1 { \str_case_e:nnF {#1} { { H } { 0.56 } { L } { 0.22 } { N } { 0.00 } } { \msg_error:nnxxx { CVSS } { invalid-option } { parseCIA } {#1} {\msg_line_context:} } } \cs_new:Npn \__CVSS_calcISS:nnn #1#2#3 { % #1 Confidentiality Impact %High H, Low L, None N % #2 Integrity Impact %High H, Low L, None N % #3 Availability Impact %High H, Low L, None N 1 - ( (1 - (\__CVSS_parseCIA:n {#1})) * (1 - (\__CVSS_parseCIA:n {#2})) * (1 - (\__CVSS_parseCIA:n {#3})) ) } \cs_new:Npn \__CVSS_calcImpact:nn #1#2 { % #1 = Scope % #2 = ISS % Scope Unchanged 6.42 × ISS % Scope Changed 7.52 × [ISS-0.029] - 3.25 × [ISS-0.02]15 \str_case_e:nnF {#1} { { U } { \fp_eval:n { 6.42 * (#2) } } % Scope UNCHANGED { C } { \fp_eval:n { 7.52 * ( (#2) - 0.029 ) - 3.25 * ( (#2) - 0.02 )^15 } } % Scope CHANGED } { \msg_error:nnxxx { CVSS } { invalid-option } { calcISC } {#1} {\msg_line_context:} } }% \cs_new:Npn \__CVSS_calcExploitability:nnnnn #1#2#3#4#5 { % #1 Attack Vector % #2 Attack Complexity % #3 Privileges Required % #4 User Interaction % #5 Scope % 8.22 × AttackVector × AttackComplexity × PrivilegeRequired × UserInteraction 8.22 * (\__CVSS_parseAV:n {#1}) * (\__CVSS_parseAC:n {#2}) * (\__CVSS_parsePR:nn {#3}{#5}) * (\__CVSS_parseUI:n {#4})% } \cs_new:Npn \__CVSS_cvssBaseScore:nnnnnnnn #1#2#3#4#5#6#7#8 { % #1 Attack Vector %Network N, Adjacent A, Local L, Physical P % #2 Attack Complexity %Low L, High H % #3 Privileges Required %None N, Low L, High H % #4 User Interaction %None N, Required R % #5 Scope %Unchanged U, Changed C % #6 Confidentiality Impact %High H, Low L, None N % #7 Integrity Impact %High H, Low L, None N % #8 Availability Impact %High H, Low L, None N % \fp_compare:nTF { \exp_args:Ne \__CVSS_calcImpact:nn {#5}{\exp_args:Ne \__CVSS_calcISS:nnn {#6}{#7}{#8}} <= 0 } % IF ISC <=0 { % ISC <=0 0.0 }{ % ISC > 0 \str_case_e:nnF {#5} { { U } { % SCOPE UNCHANGED \fp_eval:n { \__CVSS_roundup:n { min( ((\__CVSS_calcImpact:nn {#5}{\__CVSS_calcISS:nnn {#6}{#7}{#8}}) + (\__CVSS_calcExploitability:nnnnn {#1}{#2}{#3}{#4}{#5})), 10) } }% } { C } { % SCOPE CHANGED \fp_eval:n { \__CVSS_roundup:n { min( (1.08 * ((\__CVSS_calcImpact:nn {#5}{\__CVSS_calcISS:nnn {#6}{#7}{#8}}) + (\__CVSS_calcExploitability:nnnnn {#1}{#2}{#3}{#4}{#5}))), 10) } }% } } { \msg_error:nnxxx { CVSS } { invalid-option } { parseScope } {#1} {\msg_line_context:} } }% } \NewExpandableDocumentCommand \cvssScore { m }{% % Check that there are 44 chars \int_compare:nNnTF { \str_count_ignore_spaces:n {#1} } = {44}{}{ \msg_error:nnxx{CVSS}{invalid-length}{#1}{\msg_line_context:} } % Check CVSS: value \str_if_eq:eeTF {\str_range:nnn {#1} {1} {5}} {CVSS:} {} { \msg_error:nnxxx{CVSS}{invalid-structure}{AV}{\str_range:nnn {#1} {1} {5}}{\msg_line_context:} } % Check 3.1 value \str_if_eq:eeTF {\str_range:nnn {#1} {6} {8}} {3.1} {} { \msg_error:nnxxx{CVSS}{wrong-version}{3.1}{\str_range:nnn {#1} {6} {8}}{\msg_line_context:} } % Check 3.1 value \str_if_eq:eeTF {\str_range:nnn {#1} {9} {9}} {/} {} { \msg_error:nnxxx{CVSS}{wrong-version}{/}{\str_range:nnn {#1} {9} {9}}{\msg_line_context:} } % Check AV value \str_if_eq:eeTF {\str_range:nnn {#1} {10} {12}} {AV:} {} { \msg_error:nnxxx{CVSS}{invalid-structure}{AV}{\str_range:nnn {#1} {10} {12}}{\msg_line_context:} } % Check AC value \str_if_eq:eeTF {\str_range:nnn {#1} {14} {17}} {/AC:} {} { \msg_error:nnxxx{CVSS}{invalid-structure}{AC}{\str_range:nnn {#1} {14} {17}}{\msg_line_context:} } % Check PR value \str_if_eq:eeTF {\str_range:nnn {#1} {19} {22}} {/PR:} {} { \msg_error:nnxxx{CVSS}{invalid-structure}{PR}{\str_range:nnn {#1} {19} {22}}{\msg_line_context:} } % Check UI value \str_if_eq:eeTF {\str_range:nnn {#1} {24} {27}} {/UI:} {} { \msg_error:nnxxx{CVSS}{invalid-structure}{UI}{\str_range:nnn {#1} {24} {27}}{\msg_line_context:} } % Check S value \str_if_eq:eeTF {\str_range:nnn {#1} {29} {31}} {/S:} {} { \msg_error:nnxxx{CVSS}{invalid-structure}{S}{\str_range:nnn {#1} {29} {31}}{\msg_line_context:} } % Check I value \str_if_eq:eeTF {\str_range:nnn {#1} {33} {35}} {/C:} {} { \msg_error:nnxxx{CVSS}{invalid-structure}{C}{\str_range:nnn {#1} {33} {35}}{\msg_line_context:} } % Check I value \str_if_eq:eeTF {\str_range:nnn {#1} {37} {39}} {/I:} {} { \msg_error:nnxxx{CVSS}{invalid-structure}{I}{\str_range:nnn {#1} {37} {39}}{\msg_line_context:} } % Check A value \str_if_eq:eeTF {\str_range:nnn {#1} {41} {43}} {/A:} {} { \msg_error:nnxxx{CVSS}{invalid-structure}{A}{\str_range:nnn {#1} {41} {43}}{\msg_line_context:} } \exp_args:Ne \__CVSS_cvssBaseScore:nnnnnnnn { \str_use:N \str_item_ignore_spaces:nn { #1 }{ 13 } } { \str_use:N \str_item_ignore_spaces:nn { #1 }{ 18 } } { \str_use:N \str_item_ignore_spaces:nn { #1 }{ 23 } } { \str_use:N \str_item_ignore_spaces:nn { #1 }{ 28 } } { \str_use:N \str_item_ignore_spaces:nn { #1 }{ 32 } } { \str_use:N \str_item_ignore_spaces:nn { #1 }{ 36 } } { \str_use:N \str_item_ignore_spaces:nn { #1 }{ 40 } } { \str_use:N \str_item_ignore_spaces:nn { #1 }{ 44 } } }% \ExplSyntaxOff \ExplSyntaxOn \NewExpandableDocumentCommand \category { m }{% \fp_compare:nNnTF {#1}<{\scoreLow}{None} { \fp_compare:nNnTF{#1}<{\scoreMed}{Low} { \fp_compare:nNnTF{#1}<{\scoreHigh}{Medium} { \fp_compare:nNnTF{#1}<{\scoreCrit}{High} {Critical} }% }% }% }% \ExplSyntaxOff \newcommand{\cvssScorepretty}[1]{% \def\CVSScategory{\category{\cvssScore{#1}}}% \textcolor{color@cvss@\CVSScategory}{\cvssScore{#1}}% }% \newcommand{\cvssLevel}[1]{% \def\CVSSscore{\cvssScore{#1}}% \category{\CVSSscore}% }% \newcommand{\cvssLevelpretty}[1]{% \def\CVSScategory{\category{\cvssScore{#1}}}% \textcolor{color@cvss@\CVSScategory}{\CVSScategory}% }% \DeclareTotalTCBox{\cvssFrame}{m}{ enhanced,nobeforeafter, tcbox raise base, boxrule=0.4pt, top=0mm,bottom=0mm,right=1mm,left=1mm, arc=1pt, boxsep=2pt, colframe=color@cvss@#1, colback=tcbcolframe, coltext=black, }{#1}% \MakeRobust\cvssFrame \newcommand{\cvssTag}[1]{% \def\CVSSscore{\cvssScore{#1}}% \cvssFrame{\category{\CVSSscore}}% }% \newcommand{\cvssPrint}[1]{% \def\CVSSscore{\cvssScore{#1}} \cvssFrame{\category{\CVSSscore}} \quad \CVSSscore \quad% \href{https://www.first.org/cvss/calculator/3.1\##1}{#1} }% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %% Copyright (C) 2022 by Pierre VIVEGNIS %% %% This work may be distributed and/or modified under the %% conditions of the LaTeX Project Public License (LPPL), either %% version 1.3c of this license or (at your option) any later %% version. The latest version of this license is in the file: %% %% http://www.latex-project.org/lppl.txt %% %% This work is "maintained" (as per LPPL maintenance status) by %% Pierre VIVEGNIS. %% %% This work consists of the file cvss.dtx %% and the derived files cvss.ins, %% cvss.pdf and %% cvss.sty. %% %% %% End of file `cvss.ins'.