This is how I would do it:
passepartout[plot_, opt : OptionsPattern[]] := With[{
p = Show[plot, PlotRangePadding -> None]
},
Show[Show[
Graphics[{((Background /. Options[plot]) /.
Background -> Transparent),
Apply[Rectangle, Transpose[PlotRange /. Quiet@AbsoluteOptions[p]]]}],
p, Options[p]],
opt]
]
This function should be able to take any Graphics object as its argument "plot". It uses whatever Background plot has been given beforehand, and then adds the frame according to the options Background and ImagePadding supplied to the passepartout function.
For example, start with a plot
p = Plot[Sin[x], {x, 1, 10}, Frame -> True, Axes -> False, Background -> Yellow]
(I added a yellow background, but that's just for illustration and is completely optional). To get what you're looking for, just say
passepartout[p, ImagePadding -> 30, Background -> LightGray]
To make the frame thicker or asymmetric, use the standard ImagePadding syntax. You can also add other options such as AspectRatio to passpartout.
In the passepartout function, I use AbsoluteOptions to extract the PlotRange that determines the "passepartout opening." You could replace this by Options to speed things up, but the advantage of using AbsoluteOptions is that it also works for arbitrary Graphics, such as
p = Graphics[Circle[], Background -> Yellow]